<commit_before>#include <string>
#include <functional>
#include <cmath>
#include <random>
#include <experimental/optional>
#include <iostream>
#include <vector>
#include <utility>
#include <Eigen/Dense>
#include "tbb/parallel_sort.h"
#include "tbb/mutex.h"
#include "tbb/pipeline.h"

#define VALUE(x) std::cout << #x "=" << x << std::endl

namespace psh
{
	using uint = long unsigned int;

	template<uint d, class T>
	class map
	{
		static_assert(d > 0, "d must be larger than 0.");
	public:
		using point = Eigen::Matrix<uint, d, 1>;
		using opt_T = std::experimental::optional<T>;

		struct data_t
		{
			point location;
			T contents;
		};

		struct bucket : public std::vector<data_t>
		{
			uint phi_index;

			bucket(uint phi_index) : phi_index(phi_index) { }
			friend bool operator<(const bucket& lhs, const bucket& rhs) {
				return lhs.size() > rhs.size();
			}
		};

		uint M0;
		uint M1;
		uint n;
		uint m_bar;
		uint m;
		uint r_bar;
		uint r;
		std::vector<point> phi;
		std::vector<opt_T> H;
		std::default_random_engine generator;

		map(const std::vector<data_t>& data)
			: n(data.size()), m_bar(std::ceil(std::pow(n, 1.0f / d))), m(std::pow(m_bar, d)),
			  r_bar(std::ceil(std::pow(n / d, 1.0f / d)) - 1), generator(time(0))
		{
			M0 = prime();
			while ((M1 = prime()) == M0);

			VALUE(m);
			VALUE(m_bar);

			bool create_succeeded = false;

			std::uniform_int_distribution<uint> m_dist(0, m - 1);

			do
			{
				r_bar += d;
				r = std::pow(r_bar, d);
				VALUE(r);
				VALUE(r_bar);

				create_succeeded = create(data, m_dist);

			} while (!create_succeeded);
		}

		uint prime()
		{
			static const std::vector<uint> primes{ 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289,
				24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469 };
			static std::uniform_int_distribution<uint> prime_dist(0, primes.size() - 1);

			return primes[prime_dist(generator)];
		}

		bool bad_m_r()
		{
			auto m_mod_r = m_bar % r_bar;
			return m_mod_r == 1 || m_mod_r == r - 1;
		}

		void insert(const bucket& b, decltype(H)& H_hat, const decltype(phi)& phi_hat)
		{
			for (auto& element : b)
			{
				auto hashed = h(element.location, phi_hat);
				H_hat[point_to_index(hashed, m_bar, m)] = element.contents;
			}
		}

		bool jiggle_offsets(decltype(H)& H_hat, decltype(phi)& phi_hat,
			const bucket& b, std::uniform_int_distribution<uint>& m_dist)
		{
			uint start_offset = m_dist(generator);

			bool found = false;
			point found_offset;
			tbb::mutex mutex;

			uint chunk_index = 0;
			const uint num_cores = 8;
			const uint group_size = r / num_cores + 1;

			tbb::parallel_pipeline(num_cores,
				tbb::make_filter<void, uint>(tbb::filter::serial,
					[=, &chunk_index, &found, &group_size](tbb::flow_control& fc) {
						if (found || chunk_index >= r)
						{
							fc.stop();
						}
						chunk_index += group_size;
						return chunk_index;
					}) &
				tbb::make_filter<uint, void>(tbb::filter::parallel,
					[=, &mutex, &found, &found_offset, &b, &phi_hat, &H_hat](uint i0)
					{
						for (uint i = i0; i < i0 + group_size && !found; i++)
						{
							auto phi_offset = index_to_point((start_offset + i) % m, m_bar, m);

							bool collision = false;
							for (auto& element : b)
							{
								auto h0 = M0 * element.location;
								auto h1 = M1 * element.location;
								auto index = point_to_index(h1, r_bar, r);
								auto offset = index == b.phi_index ? phi_offset : phi_hat[index];
								auto hash = h0 + offset;

								collision = bool(H_hat[point_to_index(hash, m_bar, m)]);
								if (collision)
									break;
							}

							if (!collision)
							{
								tbb::mutex::scoped_lock lock(mutex);
								if (!found)
								{
									found = true;
									found_offset = phi_offset;
								}
							}
						}
					})
				);
			if (found)
			{
				phi_hat[b.phi_index] = found_offset;
				insert(b, H_hat, phi_hat);
				return true;
			}
			return false;
		}

		std::vector<bucket> create_buckets(const std::vector<data_t>& data)
		{
			std::vector<bucket> buckets;
			buckets.reserve(r);
			{
				uint i = 0;
				std::generate_n(std::back_inserter(buckets), r, [&] {
						return bucket(i++);
					});
			}

			for (auto& element : data)
			{
				auto h1 = M1 * element.location;
				buckets[point_to_index(h1, r_bar, r)].push_back(element);
			}

			std::cout << "buckets created" << std::endl;

			tbb::parallel_sort(buckets.begin(), buckets.end());
			std::cout << "buckets sorted" << std::endl;

			return buckets;
		}

		bool create(const std::vector<data_t>& data, std::uniform_int_distribution<uint>& m_dist)
		{
			decltype(phi) phi_hat;
			phi_hat.reserve(r);
			decltype(H) H_hat(m);
			std::cout << "creating " << r << " buckets" << std::endl;

			if (bad_m_r())
				return false;

			auto buckets = create_buckets(data);
			std::cout << "jiggling offsets" << std::endl;

			for (uint i = 0; i < buckets.size(); i++)
			{
				if (buckets[i].size() == 0)
					break;
				if (i % (buckets.size() / 10) == 0)
					std::cout << (100 * i) / buckets.size() << "% done" << std::endl;

				if (!jiggle_offsets(H_hat, phi_hat, buckets[i], m_dist))
				{
					return false;
				}
			}

			std::cout << "done!" << std::endl;
			phi = std::move(phi_hat);
			H = std::move(H_hat);
			return true;
		}

		constexpr uint point_to_index(const point& p, uint width, uint max) const
		{
			uint index = p[0];
			for (uint i = 1; i < d; i++)
			{
				index += uint(std::pow(width, i)) * p[i];
			}
			return index % max;
		}

		constexpr point index_to_point(uint index, uint width, uint max) const
		{
			point output;
			max /= width;
			for (uint i = 0; i < d; i++)
			{
				output[i] = index / max;
				index = index % max;

				if (i + 1 < d)
				{
					max /= width;
				}
			}

			return output;
		}

		point h(const point& p, const decltype(phi)& phi_hat) const
		{
			auto h0 = M0 * p;
			auto h1 = M1 * p;
			auto offset = phi_hat[point_to_index(h1, r_bar, r)];
			return h0 + offset;
		}

		point h(const point& p) const
		{
			return h(p, phi);
		}

		T get(const point& p) const
		{
			auto maybe_element = H[point_to_index(h(p), m_bar, m)];
			if (maybe_element)
				return maybe_element.value();
			else
				throw std::out_of_range("Element not found in map");
		}

		bool contains(const data_t& data, const decltype(H)& H_hat, const decltype(phi)& phi_hat) const
		{
			auto found = H_hat[point_to_index(h(data.location, phi_hat), m_bar, m)];
			return bool(found) && found == data.contents;
		}

		bool contains(const data_t& data) const
		{
			return contains(data, H, phi);
		}

		bool contains(const point& p, const decltype(H)& H_hat, const decltype(phi)& phi_hat) const
		{
			return bool(H_hat[point_to_index(h(p, phi_hat), m_bar, m)]);
		}

		bool contains(const point& p) const
		{
			return contains(p, H, phi);
		}

		bool contains(uint index, const data_t& data, const decltype(H)& H_hat) const
		{
			auto found = H_hat[index];
			return bool(found) && found == data.contents;
		}

		bool contains(uint index, const data_t& data) const
		{
			return contains(index, data, H);
		}

		bool contains(uint index, const decltype(H)& H_hat) const
		{
			return bool(H_hat[index]);
		}

		bool contains(uint index) const
		{
			return contains(index, H);
		}

		uint memory_size()
		{
			return sizeof(*this) + sizeof(typename decltype(phi)::value_type) * phi.size()
				+ sizeof(typename decltype(H)::value_type) * H.size();
		}
	};
}<commit_msg>specialized index and point conversions for 2 and 3 dimensions<commit_after>#include <string>
#include <functional>
#include <cmath>
#include <random>
#include <experimental/optional>
#include <iostream>
#include <vector>
#include <utility>
#include <Eigen/Dense>
#include "tbb/parallel_sort.h"
#include "tbb/mutex.h"
#include "tbb/pipeline.h"

#define VALUE(x) std::cout << #x "=" << x << std::endl

namespace psh
{
	using uint = long unsigned int;

	template<uint d, class T>
	class map
	{
		static_assert(d > 0, "d must be larger than 0.");
	public:
		using point = Eigen::Matrix<uint, d, 1>;
		using opt_T = std::experimental::optional<T>;

		struct data_t
		{
			point location;
			T contents;
		};

		struct bucket : public std::vector<data_t>
		{
			uint phi_index;

			bucket(uint phi_index) : phi_index(phi_index) { }
			friend bool operator<(const bucket& lhs, const bucket& rhs) {
				return lhs.size() > rhs.size();
			}
		};

		uint M0;
		uint M1;
		uint n;
		uint m_bar;
		uint m;
		uint r_bar;
		uint r;
		std::vector<point> phi;
		std::vector<opt_T> H;
		std::default_random_engine generator;

		map(const std::vector<data_t>& data)
			: n(data.size()), m_bar(std::ceil(std::pow(n, 1.0f / d))), m(std::pow(m_bar, d)),
			  r_bar(std::ceil(std::pow(n / d, 1.0f / d)) - 1), generator(time(0))
		{
			M0 = prime();
			while ((M1 = prime()) == M0);

			VALUE(m);
			VALUE(m_bar);

			bool create_succeeded = false;

			std::uniform_int_distribution<uint> m_dist(0, m - 1);

			do
			{
				r_bar += d;
				r = std::pow(r_bar, d);
				VALUE(r);
				VALUE(r_bar);

				create_succeeded = create(data, m_dist);

			} while (!create_succeeded);
		}

		uint prime()
		{
			static const std::vector<uint> primes{ 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289,
				24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469 };
			static std::uniform_int_distribution<uint> prime_dist(0, primes.size() - 1);

			return primes[prime_dist(generator)];
		}

		bool bad_m_r()
		{
			auto m_mod_r = m_bar % r_bar;
			return m_mod_r == 1 || m_mod_r == r - 1;
		}

		void insert(const bucket& b, decltype(H)& H_hat, const decltype(phi)& phi_hat)
		{
			for (auto& element : b)
			{
				auto hashed = h(element.location, phi_hat);
				H_hat[point_to_index(hashed, m_bar, m)] = element.contents;
			}
		}

		bool jiggle_offsets(decltype(H)& H_hat, decltype(phi)& phi_hat,
			const bucket& b, std::uniform_int_distribution<uint>& m_dist)
		{
			uint start_offset = m_dist(generator);

			bool found = false;
			point found_offset;
			tbb::mutex mutex;

			uint chunk_index = 0;
			const uint num_cores = 8;
			const uint group_size = r / num_cores + 1;

			tbb::parallel_pipeline(num_cores,
				tbb::make_filter<void, uint>(tbb::filter::serial,
					[=, &chunk_index, &found, &group_size](tbb::flow_control& fc) {
						if (found || chunk_index >= r)
						{
							fc.stop();
						}
						chunk_index += group_size;
						return chunk_index;
					}) &
				tbb::make_filter<uint, void>(tbb::filter::parallel,
					[=, &mutex, &found, &found_offset, &b, &phi_hat, &H_hat](uint i0)
					{
						for (uint i = i0; i < i0 + group_size && !found; i++)
						{
							auto phi_offset = index_to_point((start_offset + i) % m, m_bar, m);

							bool collision = false;
							for (auto& element : b)
							{
								auto h0 = M0 * element.location;
								auto h1 = M1 * element.location;
								auto index = point_to_index(h1, r_bar, r);
								auto offset = index == b.phi_index ? phi_offset : phi_hat[index];
								auto hash = h0 + offset;

								collision = bool(H_hat[point_to_index(hash, m_bar, m)]);
								if (collision)
									break;
							}

							if (!collision)
							{
								tbb::mutex::scoped_lock lock(mutex);
								if (!found)
								{
									found = true;
									found_offset = phi_offset;
								}
							}
						}
					})
				);
			if (found)
			{
				phi_hat[b.phi_index] = found_offset;
				insert(b, H_hat, phi_hat);
				return true;
			}
			return false;
		}

		std::vector<bucket> create_buckets(const std::vector<data_t>& data)
		{
			std::vector<bucket> buckets;
			buckets.reserve(r);
			{
				uint i = 0;
				std::generate_n(std::back_inserter(buckets), r, [&] {
						return bucket(i++);
					});
			}

			for (auto& element : data)
			{
				auto h1 = M1 * element.location;
				buckets[point_to_index(h1, r_bar, r)].push_back(element);
			}

			std::cout << "buckets created" << std::endl;

			tbb::parallel_sort(buckets.begin(), buckets.end());
			std::cout << "buckets sorted" << std::endl;

			return buckets;
		}

		bool create(const std::vector<data_t>& data, std::uniform_int_distribution<uint>& m_dist)
		{
			decltype(phi) phi_hat;
			phi_hat.reserve(r);
			decltype(H) H_hat(m);
			std::cout << "creating " << r << " buckets" << std::endl;

			if (bad_m_r())
				return false;

			auto buckets = create_buckets(data);
			std::cout << "jiggling offsets" << std::endl;

			for (uint i = 0; i < buckets.size(); i++)
			{
				if (buckets[i].size() == 0)
					break;
				if (i % (buckets.size() / 10) == 0)
					std::cout << (100 * i) / buckets.size() << "% done" << std::endl;

				if (!jiggle_offsets(H_hat, phi_hat, buckets[i], m_dist))
				{
					return false;
				}
			}

			std::cout << "done!" << std::endl;
			phi = std::move(phi_hat);
			H = std::move(H_hat);
			return true;
		}

		constexpr uint point_to_index(const point& p, uint width, uint max) const
		{
			if (d == 2)
			{
				return (p[0] + width * p[1]) % max;
			}
			else if (d == 3)
			{
				return (p[0] + width * p[1] + width * width * p[2]) % max;
			}
			else
			{
				uint index = p[0];
				for (uint i = 1; i < d; i++)
				{
					index += uint(std::pow(width, i)) * p[i];
				}
				return index % max;
			}
		}

		constexpr point index_to_point(uint index, uint width, uint max) const
		{
			point output;
			if (d == 2)
			{
				output << index / width, index % width;
			}
			else if (d == 3)
			{
				output <<
					index / (width * width),
					(index % (width * width)) / width,
					(index % (width * width)) % width;
			}
			else
			{
				max /= width;
				for (uint i = 0; i < d; i++)
				{
					output[i] = index / max;
					index = index % max;

					if (i + 1 < d)
					{
						max /= width;
					}
				}
			}

			return output;
		}

		point h(const point& p, const decltype(phi)& phi_hat) const
		{
			auto h0 = M0 * p;
			auto h1 = M1 * p;
			auto offset = phi_hat[point_to_index(h1, r_bar, r)];
			return h0 + offset;
		}

		point h(const point& p) const
		{
			return h(p, phi);
		}

		T get(const point& p) const
		{
			auto maybe_element = H[point_to_index(h(p), m_bar, m)];
			if (maybe_element)
				return maybe_element.value();
			else
				throw std::out_of_range("Element not found in map");
		}

		bool contains(const data_t& data, const decltype(H)& H_hat, const decltype(phi)& phi_hat) const
		{
			auto found = H_hat[point_to_index(h(data.location, phi_hat), m_bar, m)];
			return bool(found) && found == data.contents;
		}

		bool contains(const data_t& data) const
		{
			return contains(data, H, phi);
		}

		bool contains(const point& p, const decltype(H)& H_hat, const decltype(phi)& phi_hat) const
		{
			return bool(H_hat[point_to_index(h(p, phi_hat), m_bar, m)]);
		}

		bool contains(const point& p) const
		{
			return contains(p, H, phi);
		}

		bool contains(uint index, const data_t& data, const decltype(H)& H_hat) const
		{
			auto found = H_hat[index];
			return bool(found) && found == data.contents;
		}

		bool contains(uint index, const data_t& data) const
		{
			return contains(index, data, H);
		}

		bool contains(uint index, const decltype(H)& H_hat) const
		{
			return bool(H_hat[index]);
		}

		bool contains(uint index) const
		{
			return contains(index, H);
		}

		uint memory_size()
		{
			return sizeof(*this) + sizeof(typename decltype(phi)::value_type) * phi.size()
				+ sizeof(typename decltype(H)::value_type) * H.size();
		}
	};
}<|endoftext|>


<commit_before>#include "Prefetch.h"

#define CHECK_CASS(msg) if(rc != CASS_OK){ \
std::cerr<<msg<<std::endl; \
throw std::runtime_error(msg); };

Prefetch::Prefetch(const std::vector<std::pair<int64_t, int64_t>> *token_ranges, uint32_t buff_size,
                   TupleRowFactory *tuple_factory, CassSession *session, std::string query) {
    this->session = session;
    this->t_factory = tuple_factory;
    this->tokens = token_ranges;
    CassFuture *future = cass_session_prepare(session, query.c_str());
    CassError rc = cass_future_error_code(future);
    CHECK_CASS("prefetch cannot prepare");
    this->prepared_query = cass_future_get_prepared(future);
    cass_future_free(future);
    this->data.set_capacity(buff_size);
    this->worker = new std::thread{&Prefetch::consume_tokens, this};

}

PyObject* Prefetch::get_next(){
    if(completed){
        PyErr_SetNone(PyExc_StopIteration);
        return NULL;
    }
    TupleRow *response = NULL;
    data.pop(response);
    if (!response) {
        completed = true;
        PyErr_SetNone(PyExc_StopIteration);
        return NULL;
    }
    PyObject* toberet= t_factory->tuple_as_py(response);
    delete(response);
    return toberet;
}

void Prefetch::consume_tokens() {
    for (std::pair<int64_t, int64_t> range : *tokens) {
        CassStatement *statement = cass_prepared_bind(this->prepared_query);
        cass_statement_bind_int64(statement, 0, range.first);
        cass_statement_bind_int64(statement, 1, range.second);

        CassFuture *future = cass_session_execute(session, statement);
        cass_statement_free(statement);
        const CassResult *result = NULL;
        int tries = 0;
        while (result == NULL && tries < 10) {
            result = cass_future_get_result(future);
            cass_future_free(future);
            if (result == NULL) {
                CassError rc = cass_future_error_code(future);
                std::cout << cass_error_desc(rc) << std::endl;
                tries++;

            } else {
                CassIterator *iterator = cass_iterator_from_result(result);

                while (cass_iterator_next(iterator)) {
                    const CassRow *row = cass_iterator_get_row(iterator);
                    TupleRow *t = t_factory->make_tuple(row);
                    try {
                        data.push(t); //blocking operation
                    }
                    catch (tbb::user_abort &e) {
                        delete(t);
                        cass_iterator_free(iterator);
                        cass_result_free(result);
                        return;

                    }
                }
                cass_iterator_free(iterator);
                cass_result_free(result);
            }
        }
    }
    try {
        data.push(NULL);
    }
    catch (tbb::user_abort &e) {

        return;
    }
}<commit_msg>No longer returns empty list when tuple row has 0 elements<commit_after>#include "Prefetch.h"

#define CHECK_CASS(msg) if(rc != CASS_OK){ \
std::cerr<<msg<<std::endl; \
throw std::runtime_error(msg); };

Prefetch::Prefetch(const std::vector<std::pair<int64_t, int64_t>> *token_ranges, uint32_t buff_size,
                   TupleRowFactory *tuple_factory, CassSession *session, std::string query) {
    this->session = session;
    this->t_factory = tuple_factory;
    this->tokens = token_ranges;
    CassFuture *future = cass_session_prepare(session, query.c_str());
    CassError rc = cass_future_error_code(future);
    CHECK_CASS("prefetch cannot prepare");
    this->prepared_query = cass_future_get_prepared(future);
    cass_future_free(future);
    this->data.set_capacity(buff_size);
    this->worker = new std::thread{&Prefetch::consume_tokens, this};

}

PyObject* Prefetch::get_next(){
    if(completed){
        PyErr_SetNone(PyExc_StopIteration);
        return NULL;
    }
    TupleRow *response = NULL;
    data.pop(response);
    if (!response||response->n_elem()==0) {
        completed = true;
        PyErr_SetNone(PyExc_StopIteration);
        return NULL;
    }
    PyObject* toberet= t_factory->tuple_as_py(response);
    delete(response);
    return toberet;
}

void Prefetch::consume_tokens() {
    for (std::pair<int64_t, int64_t> range : *tokens) {
        CassStatement *statement = cass_prepared_bind(this->prepared_query);
        cass_statement_bind_int64(statement, 0, range.first);
        cass_statement_bind_int64(statement, 1, range.second);

        CassFuture *future = cass_session_execute(session, statement);
        cass_statement_free(statement);
        const CassResult *result = NULL;
        int tries = 0;
        while (result == NULL && tries < 10) {
            result = cass_future_get_result(future);
            cass_future_free(future);
            if (result == NULL) {
                CassError rc = cass_future_error_code(future);
                std::cout << cass_error_desc(rc) << std::endl;
                tries++;

            } else {
                CassIterator *iterator = cass_iterator_from_result(result);

                while (cass_iterator_next(iterator)) {
                    const CassRow *row = cass_iterator_get_row(iterator);
                    TupleRow *t = t_factory->make_tuple(row);
                    try {
                        data.push(t); //blocking operation
                    }
                    catch (tbb::user_abort &e) {
                        delete(t);
                        cass_iterator_free(iterator);
                        cass_result_free(result);
                        return;

                    }
                }
                cass_iterator_free(iterator);
                cass_result_free(result);
            }
        }
    }
    try {
        data.push(NULL);
    }
    catch (tbb::user_abort &e) {

        return;
    }
}<|endoftext|>


<commit_before>#include "ram.h"

/*USE EXAMPLE
Ram ram;
char *i;
i = (char*)ram.allocate(4);
strcpy(i, "siis");
std::cout << i << '\n';
ram.free(i);
*/

Ram::Ram(unsigned long blockNum, unsigned long blockSize) :memBlock(NULL), allocatedMemBlockLL(NULL), freeMemBlockLL(NULL), memPoolSize(blockNum*(blockSize + sizeof(LinkedList))), memBlockSize(blockSize){
	memBlock = malloc(memPoolSize);
	if (memBlock != NULL){
		for (unsigned long i = 0; i<blockNum; i++){
			LinkedList *currentBlock = (LinkedList*)((char*)memBlock + i*(blockSize + sizeof(LinkedList)));
			currentBlock->prev = NULL;
			currentBlock->next = freeMemBlockLL;
			if (freeMemBlockLL != NULL){
				freeMemBlockLL->prev = currentBlock;
			}
			freeMemBlockLL = currentBlock;
		}
	}
	addresses = new WORD[1024];
	processes = new PCB[30];
}
Ram::~Ram(){
	::free(memBlock);
}

void *Ram::allocate(unsigned long size, bool useMemPool){
	if (size > memBlockSize || false == useMemPool || NULL == memBlock || NULL == freeMemBlockLL){
		return malloc(size);
	}

	LinkedList *pCurUnit = freeMemBlockLL;
	freeMemBlockLL = pCurUnit->next;
	if (NULL != freeMemBlockLL)
	{
		freeMemBlockLL->prev = NULL;
	}

	pCurUnit->next = allocatedMemBlockLL;

	if (NULL != allocatedMemBlockLL)
	{
		allocatedMemBlockLL->prev = pCurUnit;
	}
	allocatedMemBlockLL = pCurUnit;
	return (void *)((char *)pCurUnit + sizeof(LinkedList));
}

void *Ram::allocate(unsigned long size, int location, PCB process, bool useMemPool)		//modified allocate method that adds the jam to the LinkedList and also in the addresses array
{
	if (size > memBlockSize || false == useMemPool || NULL == memBlock || NULL == freeMemBlockLL){
		return malloc(size);
	}

	LinkedList *pCurUnit = freeMemBlockLL;
	freeMemBlockLL = pCurUnit->next;
	if (NULL != freeMemBlockLL)
	{
		freeMemBlockLL->prev = NULL;
	}

	pCurUnit->next = allocatedMemBlockLL;

	if (NULL != allocatedMemBlockLL)
	{
		allocatedMemBlockLL->prev = pCurUnit;
	}
	allocatedMemBlockLL = pCurUnit;
	return (void *)((char *)pCurUnit + sizeof(LinkedList));

	processes[location] = process;		//saves temporary PCB information
}

void Ram::free(void *p){
	if (memBlock<p && p<(void *)((char *)memBlock + memPoolSize))
	{
		LinkedList *pCurUnit = (LinkedList *)((char *)p - sizeof(LinkedList));

		allocatedMemBlockLL = pCurUnit->next;
		if (NULL != allocatedMemBlockLL)
		{
			allocatedMemBlockLL->prev = NULL;
		}

		pCurUnit->next = freeMemBlockLL;
		if (NULL != freeMemBlockLL)
		{
			freeMemBlockLL->prev = pCurUnit;
		}

		freeMemBlockLL = pCurUnit;
	}
	else
	{
		free(p);
	}
}

///******************************************************
// * ram.cpp - RAM module implementation
// * created 150204 jonathan howard (j@hovverd.com)
// ******************************************************/
//
//#include <new>
//#include <cstdint>
//#include <cmath>
//#include <cstring>
//#include <functional>
//
//#include <iostream>
//
//#include "ram.h"
//
//#define BUFFER_SIZE (1024 * sizeof(WORD))
//#define blockSize(i) (1 << i)
//
//RAM::RAM()
//{
//    buffer = new WORD[1024]();
//    /* 2^9 (512) word base allocation */
//    ((BlockTag *)buffer)->order = 9;
//    ((BlockTag *)(buffer + blockSize(9)))->order = 9;
//
//    ((BlockTag *)buffer)->isFree = true;
//    ((BlockTag *)(buffer + blockSize(9)))->isFree = true;
//}
//
//RAM::~RAM()
//{
//    delete[] buffer;
//}
//
//WORD * RAM::allocate(std::size_t size)
//{
//	BlockTag * bestBlock = nullptr;
//
//    /* calculate order for best fit, this is ceil(log2(size))  */
//    unsigned int order = 1;
//    for (order = 0; blockSize( order ) - sizeof(BlockTag) < size; order++);
//
//    /* find best fit block to allocate in */
//	for (BlockTag * p = (BlockTag *)buffer; p != (BlockTag *)(buffer + 1024); p += blockSize(p->order))
//	{
//		if (p->isFree)
//		{
//			if ( order <= p->order )
//			{
//                /* select block if we don't have one otherwise best fit */
//                if ( bestBlock == nullptr || p->order < bestBlock->order )
//                {
//				    bestBlock = p;
//                }
//			}
//		}
//	}
//
//	if (!bestBlock)
//	{
//		throw std::bad_alloc();
//	}
//	else
//	{
//        /* subdividing block */
//        while(bestBlock->order != order)
//        {
//            bestBlock->order--;
//            BlockTag * friendBlock = (BlockTag *)((char *)bestBlock + blockSize( bestBlock->order ) * sizeof(WORD));
//
//            friendBlock->order = bestBlock->order;
//            friendBlock->isFree = true;
//
//            DLOG("[RAM] splitting block of order %i at relative address %p", bestBlock->order, (void*)((WORD *)((char *)bestBlock + sizeof(BlockTag)) - (WORD *)buffer));
//
//            /* push smaller allocations to end */
//            bestBlock = friendBlock;
//        }
//
//        bestBlock->isFree = false;
//        DLOG("[RAM] allocating %lu words at relative address %p", size, (void*)((WORD *)((char *)bestBlock + sizeof(BlockTag)) - (WORD *)buffer));
//        return (WORD *)((char *)bestBlock + sizeof(BlockTag));
//    }
//
//	return nullptr;
//}
//
//void RAM::deallocate(void * memory)
//{
//    if ( memory == nullptr )
//    {
//        return;
//    }
//
//    BlockTag * block = (BlockTag *)((char *)memory - sizeof(BlockTag));
//    BlockTag * buddy = (BlockTag *)((intptr_t)block ^ blockSize( ((BlockTag *)block)->order) );
//
//    uint8_t freeingOrder = block->order;
//
//    /* combining blocks */
//    if ( buddy->isFree )
//    {
//        freeingOrder++;
//
//        BlockTag * firstBlock;
//
//        std::less<void *> lss;
//
//        if ( lss(buddy, block) ) // | buddy | block |
//        {
//            firstBlock = (BlockTag *)buddy;
//        }
//        else // | block | buddy |
//        {
//            firstBlock = (BlockTag *)block;
//        }
//        /* Zero both blocks simultaneously */
//        memset(firstBlock, 0, blockSize( freeingOrder ) * sizeof(WORD));
//
//        firstBlock->isFree = true;
//        firstBlock->order = freeingOrder;
//
//        DLOG("[RAM] deallocating %i words by combining blocks at relative addresses %p and %p", blockSize(freeingOrder), block, buddy);
//    }
//    else /* freeing a single block */
//    {
//        memset(block, 0, blockSize( freeingOrder ) * sizeof(WORD));
//        block->isFree = true;
//        block->order  = freeingOrder;
//
//        DLOG("[RAM] deallocating %i words in single block at %p", blockSize( freeingOrder ), block);
//    }
//
//    std::cout << buffer << std::endl << block << std::endl << buddy << std::endl << block - buddy << std::endl;
//}
//
//#undef BUFFER_SIZE
<commit_msg>Syntax correction<commit_after>#include "ram.h"

/*USE EXAMPLE
Ram ram;
char *i;
i = (char*)ram.allocate(4);
strcpy(i, "siis");
std::cout << i << '\n';
ram.free(i);
*/

Ram::Ram(unsigned long blockNum, unsigned long blockSize) :memBlock(NULL), allocatedMemBlockLL(NULL), freeMemBlockLL(NULL), memPoolSize(blockNum*(blockSize + sizeof(LinkedList))), memBlockSize(blockSize){
	memBlock = malloc(memPoolSize);
	if (memBlock != NULL){
		for (unsigned long i = 0; i<blockNum; i++){
			LinkedList *currentBlock = (LinkedList*)((char*)memBlock + i*(blockSize + sizeof(LinkedList)));
			currentBlock->prev = NULL;
			currentBlock->next = freeMemBlockLL;
			if (freeMemBlockLL != NULL){
				freeMemBlockLL->prev = currentBlock;
			}
			freeMemBlockLL = currentBlock;
		}
	}
	addresses = new WORD[1024];
	processes = new PCB[30];
}
Ram::~Ram(){
	::free(memBlock);
}

void *Ram::allocate(unsigned long size, bool useMemPool){
	if (size > memBlockSize || false == useMemPool || NULL == memBlock || NULL == freeMemBlockLL){
		return malloc(size);
	}

	LinkedList *pCurUnit = freeMemBlockLL;
	freeMemBlockLL = pCurUnit->next;
	if (freeMemBlockLL != NULL)
	{
		freeMemBlockLL->prev = NULL;
	}

	pCurUnit->next = allocatedMemBlockLL;

	if (allocatedMemBlockLL != NULL)
	{
		allocatedMemBlockLL->prev = pCurUnit;
	}
	allocatedMemBlockLL = pCurUnit;
	return (void *)((char *)pCurUnit + sizeof(LinkedList));
}

void *Ram::allocate(unsigned long size, int location, PCB process, bool useMemPool)		//modified allocate method that adds the jam to the LinkedList and also in the addresses array
{
	if (size > memBlockSize || false == useMemPool || NULL == memBlock || NULL == freeMemBlockLL){
		return malloc(size);
	}

	LinkedList *pCurUnit = freeMemBlockLL;
	freeMemBlockLL = pCurUnit->next;
	if (freeMemBlockLL != NULL)
	{
		freeMemBlockLL->prev = NULL;
	}

	pCurUnit->next = allocatedMemBlockLL;

	if (allocatedMemBlockLL != NULL)
	{
		allocatedMemBlockLL->prev = pCurUnit;
	}
	allocatedMemBlockLL = pCurUnit;
	return (void *)((char *)pCurUnit + sizeof(LinkedList));

	processes[location] = process;		//saves temporary PCB information
}

void Ram::free(void *p){
	if (memBlock<p && p<(void *)((char *)memBlock + memPoolSize))
	{
		LinkedList *pCurUnit = (LinkedList *)((char *)p - sizeof(LinkedList));

		allocatedMemBlockLL = pCurUnit->next;
		if (allocatedMemBlockLL != NULL)
		{
			allocatedMemBlockLL->prev = NULL;
		}

		pCurUnit->next = freeMemBlockLL;
		if (freeMemBlockLL != NULL)
		{
			freeMemBlockLL->prev = pCurUnit;
		}

		freeMemBlockLL = pCurUnit;
	}
	else
	{
		free(p);
	}
}

///******************************************************
// * ram.cpp - RAM module implementation
// * created 150204 jonathan howard (j@hovverd.com)
// ******************************************************/
//
//#include <new>
//#include <cstdint>
//#include <cmath>
//#include <cstring>
//#include <functional>
//
//#include <iostream>
//
//#include "ram.h"
//
//#define BUFFER_SIZE (1024 * sizeof(WORD))
//#define blockSize(i) (1 << i)
//
//RAM::RAM()
//{
//    buffer = new WORD[1024]();
//    /* 2^9 (512) word base allocation */
//    ((BlockTag *)buffer)->order = 9;
//    ((BlockTag *)(buffer + blockSize(9)))->order = 9;
//
//    ((BlockTag *)buffer)->isFree = true;
//    ((BlockTag *)(buffer + blockSize(9)))->isFree = true;
//}
//
//RAM::~RAM()
//{
//    delete[] buffer;
//}
//
//WORD * RAM::allocate(std::size_t size)
//{
//	BlockTag * bestBlock = nullptr;
//
//    /* calculate order for best fit, this is ceil(log2(size))  */
//    unsigned int order = 1;
//    for (order = 0; blockSize( order ) - sizeof(BlockTag) < size; order++);
//
//    /* find best fit block to allocate in */
//	for (BlockTag * p = (BlockTag *)buffer; p != (BlockTag *)(buffer + 1024); p += blockSize(p->order))
//	{
//		if (p->isFree)
//		{
//			if ( order <= p->order )
//			{
//                /* select block if we don't have one otherwise best fit */
//                if ( bestBlock == nullptr || p->order < bestBlock->order )
//                {
//				    bestBlock = p;
//                }
//			}
//		}
//	}
//
//	if (!bestBlock)
//	{
//		throw std::bad_alloc();
//	}
//	else
//	{
//        /* subdividing block */
//        while(bestBlock->order != order)
//        {
//            bestBlock->order--;
//            BlockTag * friendBlock = (BlockTag *)((char *)bestBlock + blockSize( bestBlock->order ) * sizeof(WORD));
//
//            friendBlock->order = bestBlock->order;
//            friendBlock->isFree = true;
//
//            DLOG("[RAM] splitting block of order %i at relative address %p", bestBlock->order, (void*)((WORD *)((char *)bestBlock + sizeof(BlockTag)) - (WORD *)buffer));
//
//            /* push smaller allocations to end */
//            bestBlock = friendBlock;
//        }
//
//        bestBlock->isFree = false;
//        DLOG("[RAM] allocating %lu words at relative address %p", size, (void*)((WORD *)((char *)bestBlock + sizeof(BlockTag)) - (WORD *)buffer));
//        return (WORD *)((char *)bestBlock + sizeof(BlockTag));
//    }
//
//	return nullptr;
//}
//
//void RAM::deallocate(void * memory)
//{
//    if ( memory == nullptr )
//    {
//        return;
//    }
//
//    BlockTag * block = (BlockTag *)((char *)memory - sizeof(BlockTag));
//    BlockTag * buddy = (BlockTag *)((intptr_t)block ^ blockSize( ((BlockTag *)block)->order) );
//
//    uint8_t freeingOrder = block->order;
//
//    /* combining blocks */
//    if ( buddy->isFree )
//    {
//        freeingOrder++;
//
//        BlockTag * firstBlock;
//
//        std::less<void *> lss;
//
//        if ( lss(buddy, block) ) // | buddy | block |
//        {
//            firstBlock = (BlockTag *)buddy;
//        }
//        else // | block | buddy |
//        {
//            firstBlock = (BlockTag *)block;
//        }
//        /* Zero both blocks simultaneously */
//        memset(firstBlock, 0, blockSize( freeingOrder ) * sizeof(WORD));
//
//        firstBlock->isFree = true;
//        firstBlock->order = freeingOrder;
//
//        DLOG("[RAM] deallocating %i words by combining blocks at relative addresses %p and %p", blockSize(freeingOrder), block, buddy);
//    }
//    else /* freeing a single block */
//    {
//        memset(block, 0, blockSize( freeingOrder ) * sizeof(WORD));
//        block->isFree = true;
//        block->order  = freeingOrder;
//
//        DLOG("[RAM] deallocating %i words in single block at %p", blockSize( freeingOrder ), block);
//    }
//
//    std::cout << buffer << std::endl << block << std::endl << buddy << std::endl << block - buddy << std::endl;
//}
//
//#undef BUFFER_SIZE
<|endoftext|>


<commit_before>// Module:  Log4CPLUS
// File:    ndc.cxx
// Created: 6/2001
// Author:  Tad E. Smith
//
//
// Copyright 2001-2015 Tad E. Smith
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <log4cplus/ndc.h>
#include <log4cplus/internal/internal.h>
#include <utility>
#include <algorithm>

#if defined (LOG4CPLUS_WITH_UNIT_TESTS)
#include <catch.hpp>
#endif

namespace log4cplus
{

///////////////////////////////////////////////////////////////////////////////
// log4cplus::DiagnosticContext ctors
///////////////////////////////////////////////////////////////////////////////

namespace
{

static
void
init_full_message (log4cplus::tstring & fullMessage,
    log4cplus::tstring const & message, DiagnosticContext const * parent)
{
    if (parent)
    {
        fullMessage.reserve (parent->fullMessage.size () + 1
            + message.size ());
        fullMessage = parent->fullMessage;
        fullMessage += LOG4CPLUS_TEXT(" ");
        fullMessage += message;
    }
    else
        fullMessage = message;
}

} // namespace

DiagnosticContext::DiagnosticContext(const log4cplus::tstring& message_,
                                     DiagnosticContext const * parent)
    : message(message_)
    , fullMessage()
{
    init_full_message (fullMessage, message, parent);
}

DiagnosticContext::DiagnosticContext(tchar const * message_,
                                     DiagnosticContext const * parent)
    : message(message_)
    , fullMessage()
{
    init_full_message (fullMessage, message, parent);
}

DiagnosticContext::DiagnosticContext(const log4cplus::tstring& message_)
    : message(message_)
    , fullMessage(message)
{
}

DiagnosticContext::DiagnosticContext(tchar const * message_)
    : message(message_)
    , fullMessage(message)
{
}

DiagnosticContext::DiagnosticContext (DiagnosticContext const & other)
    : message (other.message)
    , fullMessage (other.fullMessage)
{ }

DiagnosticContext & DiagnosticContext::operator = (
    DiagnosticContext const & other)
{
    DiagnosticContext (other).swap (*this);
    return *this;
}

DiagnosticContext::DiagnosticContext (DiagnosticContext && other)
    : message (std::move (other.message))
    , fullMessage (std::move (other.fullMessage))
{ }

DiagnosticContext &
DiagnosticContext::operator = (DiagnosticContext && other)
{
    DiagnosticContext (std::move (other)).swap (*this);
    return *this;
}

void
DiagnosticContext::swap (DiagnosticContext & other)
{
    using std::swap;
    swap (message, other.message);
    swap (fullMessage, other.fullMessage);
}

///////////////////////////////////////////////////////////////////////////////
// log4cplus::NDC ctor and dtor
///////////////////////////////////////////////////////////////////////////////

NDC::NDC()
{ }

NDC::~NDC()
{ }

///////////////////////////////////////////////////////////////////////////////
// log4cplus::NDC public methods
///////////////////////////////////////////////////////////////////////////////

void
NDC::clear()
{
    DiagnosticContextStack* ptr = getPtr();
    DiagnosticContextStack ().swap (*ptr);
}

void
NDC::remove()
{
    clear();
}

DiagnosticContextStack
NDC::cloneStack() const
{
    DiagnosticContextStack* ptr = getPtr();
    return DiagnosticContextStack(*ptr);
}

void
NDC::inherit(const DiagnosticContextStack& stack)
{
    DiagnosticContextStack* ptr = getPtr();
    DiagnosticContextStack (stack).swap (*ptr);
}

log4cplus::tstring const &
NDC::get() const
{
    DiagnosticContextStack* ptr = getPtr();
    if(!ptr->empty())
        return ptr->back().fullMessage;
    else
        return internal::empty_str;
}

std::size_t
NDC::getDepth() const
{
    DiagnosticContextStack* ptr = getPtr();
    return ptr->size();
}

log4cplus::tstring
NDC::pop()
{
    DiagnosticContextStack* ptr = getPtr();
    if(!ptr->empty())
    {
        tstring message;
        message.swap (ptr->back ().message);
        ptr->pop_back();
        return message;
    }
    else
        return log4cplus::tstring ();
}

void
NDC::pop_void ()
{
    DiagnosticContextStack* ptr = getPtr ();
    if (! ptr->empty ())
        ptr->pop_back ();
}

log4cplus::tstring const &
NDC::peek() const
{
    DiagnosticContextStack* ptr = getPtr();
    if(!ptr->empty())
        return ptr->back().message;
    else
        return internal::empty_str;
}

void
NDC::push(const log4cplus::tstring& message)
{
    push_worker (message);
}

void
NDC::push(tchar const * message)
{
    push_worker (message);
}

template <typename StringType>
void
NDC::push_worker (StringType const & message)
{
    DiagnosticContextStack* ptr = getPtr();
    if (ptr->empty())
        ptr->push_back( DiagnosticContext(message, nullptr) );
    else
    {
        DiagnosticContext const & dc = ptr->back();
        ptr->push_back( DiagnosticContext(message, &dc) );
    }
}

void
NDC::setMaxDepth(std::size_t maxDepth)
{
    DiagnosticContextStack* ptr = getPtr();
    while(maxDepth < ptr->size())
        ptr->pop_back();
}

DiagnosticContextStack* NDC::getPtr()
{
    internal::per_thread_data * ptd = internal::get_ptd ();
    return &ptd->ndc_dcs;
}

//
//
//

NDCContextCreator::NDCContextCreator(const log4cplus::tstring& msg)
{
    getNDC().push(msg);
}

NDCContextCreator::NDCContextCreator(tchar const * msg)
{
    getNDC().push(msg);
}

NDCContextCreator::~NDCContextCreator()
{
    getNDC().pop_void();
}

#if defined (LOG4CPLUS_WITH_UNIT_TESTS)
CATCH_TEST_CASE ("NDC", "[NDC]")
{
    NDC & ndc = getNDC ();
    static tchar const CONTEXT1[] = LOG4CPLUS_TEXT ("c1");
    static tchar const CONTEXT2[] = LOG4CPLUS_TEXT ("c2");
    static tchar const CONTEXT3[] = LOG4CPLUS_TEXT ("c3");
    static tstring const C1C2 = tstring (CONTEXT1)
        + LOG4CPLUS_TEXT (' ')
        + CONTEXT2;
    static tstring const C1C2C3 = C1C2
        + LOG4CPLUS_TEXT (' ')
        + CONTEXT3;

    CATCH_SECTION ("basic")
    {
        CATCH_REQUIRE (ndc.get ().empty ());
        CATCH_REQUIRE (ndc.peek ().empty ());
        CATCH_REQUIRE (ndc.getDepth () == 0);
        NDCContextCreator c1 (CONTEXT1);
        CATCH_REQUIRE (ndc.peek () == CONTEXT1);
        CATCH_REQUIRE (ndc.get () == CONTEXT1);
        CATCH_REQUIRE (ndc.getDepth () == 1);
        {
            NDCContextCreator c2 (LOG4CPLUS_C_STR_TO_TSTRING (CONTEXT2));
            CATCH_REQUIRE (ndc.get () == C1C2);
            CATCH_REQUIRE (ndc.getDepth () == 2);
            CATCH_REQUIRE (ndc.peek () == CONTEXT2);

            ndc.push (CONTEXT3);
            CATCH_REQUIRE (ndc.get () == C1C2C3);
            CATCH_REQUIRE (ndc.peek () == CONTEXT3);
            CATCH_REQUIRE (ndc.pop () == CONTEXT3);
        }
        CATCH_REQUIRE (ndc.peek () == CONTEXT1);
        CATCH_REQUIRE (ndc.get () == CONTEXT1);
        CATCH_REQUIRE (ndc.getDepth () == 1);
    }

    CATCH_SECTION ("remove")
    {
        ndc.push (CONTEXT1);
        CATCH_REQUIRE (ndc.peek () == CONTEXT1);
        CATCH_REQUIRE (ndc.get () == CONTEXT1);
        CATCH_REQUIRE (ndc.getDepth () == 1);

        ndc.remove ();
        CATCH_REQUIRE (ndc.get ().empty ());
        CATCH_REQUIRE (ndc.peek ().empty ());
        CATCH_REQUIRE (ndc.getDepth () == 0);
    }
}

#endif

} // namespace log4cplus
<commit_msg>Clear NDC before each test.<commit_after>// Module:  Log4CPLUS
// File:    ndc.cxx
// Created: 6/2001
// Author:  Tad E. Smith
//
//
// Copyright 2001-2015 Tad E. Smith
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <log4cplus/ndc.h>
#include <log4cplus/internal/internal.h>
#include <utility>
#include <algorithm>

#if defined (LOG4CPLUS_WITH_UNIT_TESTS)
#include <catch.hpp>
#endif

namespace log4cplus
{

///////////////////////////////////////////////////////////////////////////////
// log4cplus::DiagnosticContext ctors
///////////////////////////////////////////////////////////////////////////////

namespace
{

static
void
init_full_message (log4cplus::tstring & fullMessage,
    log4cplus::tstring const & message, DiagnosticContext const * parent)
{
    if (parent)
    {
        fullMessage.reserve (parent->fullMessage.size () + 1
            + message.size ());
        fullMessage = parent->fullMessage;
        fullMessage += LOG4CPLUS_TEXT(" ");
        fullMessage += message;
    }
    else
        fullMessage = message;
}

} // namespace

DiagnosticContext::DiagnosticContext(const log4cplus::tstring& message_,
                                     DiagnosticContext const * parent)
    : message(message_)
    , fullMessage()
{
    init_full_message (fullMessage, message, parent);
}

DiagnosticContext::DiagnosticContext(tchar const * message_,
                                     DiagnosticContext const * parent)
    : message(message_)
    , fullMessage()
{
    init_full_message (fullMessage, message, parent);
}

DiagnosticContext::DiagnosticContext(const log4cplus::tstring& message_)
    : message(message_)
    , fullMessage(message)
{
}

DiagnosticContext::DiagnosticContext(tchar const * message_)
    : message(message_)
    , fullMessage(message)
{
}

DiagnosticContext::DiagnosticContext (DiagnosticContext const & other)
    : message (other.message)
    , fullMessage (other.fullMessage)
{ }

DiagnosticContext & DiagnosticContext::operator = (
    DiagnosticContext const & other)
{
    DiagnosticContext (other).swap (*this);
    return *this;
}

DiagnosticContext::DiagnosticContext (DiagnosticContext && other)
    : message (std::move (other.message))
    , fullMessage (std::move (other.fullMessage))
{ }

DiagnosticContext &
DiagnosticContext::operator = (DiagnosticContext && other)
{
    DiagnosticContext (std::move (other)).swap (*this);
    return *this;
}

void
DiagnosticContext::swap (DiagnosticContext & other)
{
    using std::swap;
    swap (message, other.message);
    swap (fullMessage, other.fullMessage);
}

///////////////////////////////////////////////////////////////////////////////
// log4cplus::NDC ctor and dtor
///////////////////////////////////////////////////////////////////////////////

NDC::NDC()
{ }

NDC::~NDC()
{ }

///////////////////////////////////////////////////////////////////////////////
// log4cplus::NDC public methods
///////////////////////////////////////////////////////////////////////////////

void
NDC::clear()
{
    DiagnosticContextStack* ptr = getPtr();
    DiagnosticContextStack ().swap (*ptr);
}

void
NDC::remove()
{
    clear();
}

DiagnosticContextStack
NDC::cloneStack() const
{
    DiagnosticContextStack* ptr = getPtr();
    return DiagnosticContextStack(*ptr);
}

void
NDC::inherit(const DiagnosticContextStack& stack)
{
    DiagnosticContextStack* ptr = getPtr();
    DiagnosticContextStack (stack).swap (*ptr);
}

log4cplus::tstring const &
NDC::get() const
{
    DiagnosticContextStack* ptr = getPtr();
    if(!ptr->empty())
        return ptr->back().fullMessage;
    else
        return internal::empty_str;
}

std::size_t
NDC::getDepth() const
{
    DiagnosticContextStack* ptr = getPtr();
    return ptr->size();
}

log4cplus::tstring
NDC::pop()
{
    DiagnosticContextStack* ptr = getPtr();
    if(!ptr->empty())
    {
        tstring message;
        message.swap (ptr->back ().message);
        ptr->pop_back();
        return message;
    }
    else
        return log4cplus::tstring ();
}

void
NDC::pop_void ()
{
    DiagnosticContextStack* ptr = getPtr ();
    if (! ptr->empty ())
        ptr->pop_back ();
}

log4cplus::tstring const &
NDC::peek() const
{
    DiagnosticContextStack* ptr = getPtr();
    if(!ptr->empty())
        return ptr->back().message;
    else
        return internal::empty_str;
}

void
NDC::push(const log4cplus::tstring& message)
{
    push_worker (message);
}

void
NDC::push(tchar const * message)
{
    push_worker (message);
}

template <typename StringType>
void
NDC::push_worker (StringType const & message)
{
    DiagnosticContextStack* ptr = getPtr();
    if (ptr->empty())
        ptr->push_back( DiagnosticContext(message, nullptr) );
    else
    {
        DiagnosticContext const & dc = ptr->back();
        ptr->push_back( DiagnosticContext(message, &dc) );
    }
}

void
NDC::setMaxDepth(std::size_t maxDepth)
{
    DiagnosticContextStack* ptr = getPtr();
    while(maxDepth < ptr->size())
        ptr->pop_back();
}

DiagnosticContextStack* NDC::getPtr()
{
    internal::per_thread_data * ptd = internal::get_ptd ();
    return &ptd->ndc_dcs;
}

//
//
//

NDCContextCreator::NDCContextCreator(const log4cplus::tstring& msg)
{
    getNDC().push(msg);
}

NDCContextCreator::NDCContextCreator(tchar const * msg)
{
    getNDC().push(msg);
}

NDCContextCreator::~NDCContextCreator()
{
    getNDC().pop_void();
}

#if defined (LOG4CPLUS_WITH_UNIT_TESTS)
CATCH_TEST_CASE ("NDC", "[NDC]")
{
    NDC & ndc = getNDC ();
    ndc.clear ();
    static tchar const CONTEXT1[] = LOG4CPLUS_TEXT ("c1");
    static tchar const CONTEXT2[] = LOG4CPLUS_TEXT ("c2");
    static tchar const CONTEXT3[] = LOG4CPLUS_TEXT ("c3");
    static tstring const C1C2 = tstring (CONTEXT1)
        + LOG4CPLUS_TEXT (' ')
        + CONTEXT2;
    static tstring const C1C2C3 = C1C2
        + LOG4CPLUS_TEXT (' ')
        + CONTEXT3;

    CATCH_SECTION ("basic")
    {
        CATCH_REQUIRE (ndc.get ().empty ());
        CATCH_REQUIRE (ndc.peek ().empty ());
        CATCH_REQUIRE (ndc.getDepth () == 0);
        NDCContextCreator c1 (CONTEXT1);
        CATCH_REQUIRE (ndc.peek () == CONTEXT1);
        CATCH_REQUIRE (ndc.get () == CONTEXT1);
        CATCH_REQUIRE (ndc.getDepth () == 1);
        {
            NDCContextCreator c2 (LOG4CPLUS_C_STR_TO_TSTRING (CONTEXT2));
            CATCH_REQUIRE (ndc.get () == C1C2);
            CATCH_REQUIRE (ndc.getDepth () == 2);
            CATCH_REQUIRE (ndc.peek () == CONTEXT2);

            ndc.push (CONTEXT3);
            CATCH_REQUIRE (ndc.get () == C1C2C3);
            CATCH_REQUIRE (ndc.peek () == CONTEXT3);
            CATCH_REQUIRE (ndc.pop () == CONTEXT3);
        }
        CATCH_REQUIRE (ndc.peek () == CONTEXT1);
        CATCH_REQUIRE (ndc.get () == CONTEXT1);
        CATCH_REQUIRE (ndc.getDepth () == 1);
    }

    CATCH_SECTION ("remove")
    {
        ndc.push (CONTEXT1);
        CATCH_REQUIRE (ndc.peek () == CONTEXT1);
        CATCH_REQUIRE (ndc.get () == CONTEXT1);
        CATCH_REQUIRE (ndc.getDepth () == 1);

        ndc.remove ();
        CATCH_REQUIRE (ndc.get ().empty ());
        CATCH_REQUIRE (ndc.peek ().empty ());
        CATCH_REQUIRE (ndc.getDepth () == 0);
    }
}

#endif

} // namespace log4cplus
<|endoftext|>


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

#include "Box.h"

#include <GL/gl.h>
#include <GL/glu.h>

#include <stdio.h>

#include "CSSStyleDeclarationImp.h"
#include "ViewCSSImp.h"

#include "font/FontManager.h"
#include "font/FontManagerBackEndGL.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

namespace {

enum
{
    TOP,
    RIGHT,
    BOTTOM,
    LEFT
};

std::map<uint8_t*, GLuint> texnames;

GLuint addImage(uint8_t* image, unsigned width, unsigned heigth, unsigned repeat, GLenum format)
{
    GLuint texname;

    glGenTextures(1, &texname);
    glBindTexture(GL_TEXTURE_2D, texname);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (repeat & BoxImage::RepeatS) ? GL_REPEAT : (repeat & BoxImage::Clamp) ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (repeat & BoxImage::RepeatT) ? GL_REPEAT : (repeat & BoxImage::Clamp) ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, heigth, 0, format, GL_UNSIGNED_BYTE, image);
    texnames.insert(std::pair<uint8_t*, GLuint>(image, texname));
    return texname;
}

GLuint getTexname(uint8_t* image, unsigned width, unsigned height, unsigned repeat, GLenum format)
{
    std::map<uint8_t*, GLuint>::iterator it = texnames.find(image);
    if (it == texnames.end())
        return addImage(image, width, height, repeat, format);
    return it->second;
}

void deleteImage(uint8_t* image)
{
    std::map<uint8_t*, GLuint>::iterator it = texnames.find(image);
    if (it != texnames.end()) {
        glDeleteTextures(1, &it->second);
        texnames.erase(it);
    }
}

void getOriginScreenPosition(float& x, float& y)
{
    GLfloat m[16];
    glGetFloatv(GL_MODELVIEW_MATRIX, m);
    x = m[12];
    y = glutGet(GLUT_WINDOW_HEIGHT) - m[13];
}

}  // namespace

BoxImage::~BoxImage()
{
    if (state == CompletelyAvailable)
        deleteImage(pixels);
    delete pixels;
}

void BoxImage::render(ViewCSSImp* view, float x, float y, float width, float height, float left, float top)
{
    if (state != CompletelyAvailable)
        return;

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    if (repeat & BoxImage::Clamp)
        glScalef(1.0f / width, 1.0f / height, 0.0f);
    else
        glScalef(1.0f / naturalWidth, 1.0f / naturalHeight, 0.0f);
    glMatrixMode(GL_MODELVIEW);

    GLuint texname = getTexname(pixels, naturalWidth, naturalHeight, repeat, format);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texname);
    glColor3ub(255, 255, 255);
    glBegin(GL_QUADS);
            glTexCoord2f(x - left, y - top);
            glVertex2f(x, y);
            glTexCoord2f(x - left + width, y - top);
            glVertex2f(x + width, y);
            glTexCoord2f(x - left + width, y - top + height);
            glVertex2f(x + width, y + height);
            glTexCoord2f(x - left, y - top + height);
            glVertex2f(x, y + height);
    glEnd();
    glDisable(GL_TEXTURE_2D);
}

void Box::renderBorderEdge(ViewCSSImp* view, int edge, unsigned borderStyle, unsigned color,
                           float a, float b, float c, float d,
                           float e, float f, float g, float h)
{
    if (borderStyle == CSSBorderStyleValueImp::None ||
        borderStyle == CSSBorderStyleValueImp::Hidden)
        return;

    GLubyte red = color >> 16;
    GLubyte green = color >> 8;
    GLubyte blue = color;
    GLubyte alpha = color >> 24;

    if (borderStyle == CSSBorderStyleValueImp::Double) {
        float offset;
        offset = (g - a) / 3;
        float i = a + offset;
        float m = g - offset;
        offset = (h - b) / 3;
        float j = b + offset;
        float n = h - offset;
        offset = (c - e) / 3;
        float k = c - offset;
        float o = e + offset;
        offset = (f - d) / 3;
        float l = d + offset;
        float p = f - offset;
        glColor4ub(red, green, blue, alpha);
        glBegin(GL_QUADS);
            glVertex2f(a, b);
            glVertex2f(c, d);
            glVertex2f(k, l);
            glVertex2f(i, j);
        glEnd();
        glBegin(GL_QUADS);
            glVertex2f(m, n);
            glVertex2f(o, p);
            glVertex2f(e, f);
            glVertex2f(g, h);
        glEnd();
        return;
    }

    if (borderStyle == CSSBorderStyleValueImp::Dotted ||
        borderStyle == CSSBorderStyleValueImp::Dashed) {
        glEnable(GL_LINE_STIPPLE);
        glLineWidth(fabsf(g - a));
        glLineStipple(fabsf(g - a), (borderStyle == CSSBorderStyleValueImp::Dotted) ? 0xaaaa : 0xcccc);
        glBegin(GL_LINES);
            glColor4ub(red, green, blue, alpha);
            glVertex2f((a + g) / 2, (b + h) / 2);
            glVertex2f((c + e) / 2, (d + f) / 2);
        glEnd();
        glDisable(GL_LINE_STIPPLE);
        return;
    }

    if (borderStyle == CSSBorderStyleValueImp::Groove ||
        borderStyle == CSSBorderStyleValueImp::Ridge) {
        GLubyte redDark = std::max(red - 128, 0);
        GLubyte greenDark = std::max(green - 128, 0);
        GLubyte blueDark = std::max(blue - 128, 0);
        GLubyte redBright = std::min(red + 128, 255);
        GLubyte greenBright = std::min(green + 128, 255);
        GLubyte blueBright = std::min(blue + 128, 255);
        float offset;
        offset = (g - a) / 2;
        float i = a + offset;
        offset = (h - b) / 2;
        float j = b + offset;
        offset = (c - e) / 2;
        float k = c - offset;
        offset = (f - d) / 2;
        float l = d + offset;
        if (borderStyle == CSSBorderStyleValueImp::Groove)
            glColor4ub(redDark, greenDark, blueDark, alpha);
        else
            glColor4ub(redBright, greenBright, blueBright, alpha);
        glBegin(GL_QUADS);
            glVertex2f(a, b);
            glVertex2f(c, d);
            glVertex2f(k, l);
            glVertex2f(i, j);
        glEnd();
        if (borderStyle == CSSBorderStyleValueImp::Groove)
            glColor4ub(redBright, greenBright, blueBright, alpha);
        else
            glColor4ub(redDark, greenDark, blueDark, alpha);
        glBegin(GL_QUADS);
            glVertex2f(i, j);
            glVertex2f(k, l);
            glVertex2f(e, f);
            glVertex2f(g, h);
        glEnd();
        return;
    }

    if (borderStyle == CSSBorderStyleValueImp::Inset ||
        borderStyle == CSSBorderStyleValueImp::Outset) {
        bool dark = false;
        bool bright = false;
        if (borderStyle == CSSBorderStyleValueImp::Inset) {
            switch (edge) {
            case TOP:
            case LEFT:
                dark = true;
                break;;
            case RIGHT:
            case BOTTOM:
                bright = true;
                break;;
            }
        }
        if (borderStyle == CSSBorderStyleValueImp::Outset) {
            switch (edge) {
            case TOP:
            case LEFT:
                bright = true;
                break;;
            case RIGHT:
            case BOTTOM:
                dark = true;
                break;;
            }
        }
        if (dark) {
            red = std::max(red - 128, 0);
            green = std::max(green - 128, 0);
            blue = std::max(blue - 128, 0);
        } else if (bright) {
            red = std::min(red + 128, 255);
            green = std::min(green + 128, 255);
            blue = std::min(blue + 128, 255);
        }
    }

    glColor4ub(red, green, blue, alpha);
    glBegin(GL_QUADS);
        glVertex2f(a, b);
        glVertex2f(c, d);
        glVertex2f(e, f);
        glVertex2f(g, h);
    glEnd();
}

void Box::renderBorder(ViewCSSImp* view)
{
    glDisable(GL_TEXTURE_2D);

    float ll = marginLeft;
    float lr = ll + borderLeft;
    float rl = lr + paddingLeft + width + paddingRight;
    float rr = rl + borderRight;
    float tt = marginTop;
    float tb = tt + borderTop;
    float bt = tb + paddingTop + height + paddingBottom;
    float bb = bt + borderBottom;

    if (backgroundColor != 0x00000000) {
        glColor4ub(backgroundColor >> 16, backgroundColor >> 8, backgroundColor, backgroundColor >> 24);
        glBegin(GL_QUADS);
            glVertex2f(lr, tb);
            glVertex2f(rl, tb);
            glVertex2f(rl, bt);
            glVertex2f(lr, bt);
        glEnd();
    }

    if (backgroundImage) {
        GLfloat border[] = { ((backgroundColor >> 16) & 0xff) / 255.0f,
                             ((backgroundColor >> 8) & 0xff) / 255.0f,
                             ((backgroundColor) & 0xff) / 255.0f,
                             ((backgroundColor >> 24) & 0xff) / 255.0f };
        glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
        glPushMatrix();
        if (getParentBox()) {
            // TODO: check padding
            glTranslatef(lr, tb, 0.0f);
            backgroundImage->render(view, 0, 0, rl - lr, bt - tb, backgroundLeft, backgroundTop);
        } else {
            const ContainingBlock* containingBlock = getContainingBlock(view);
            glTranslatef(ll, tt, 0.0f);
            backgroundImage->render(view, -ll, -tt, containingBlock->width, containingBlock->height, backgroundLeft, backgroundTop);
        }
        glPopMatrix();
    }

    if (borderTop)
        renderBorderEdge(view, TOP,
                         style->borderTopStyle.getValue(),
                         style->borderTopColor.getARGB(),
                         ll, tt, rr, tt, rl, tb, lr, tb);
    if (borderRight)
        renderBorderEdge(view, RIGHT,
                         style->borderRightStyle.getValue(),
                         style->borderRightColor.getARGB(),
                         rl, bt, rl, tb, rr, tt, rr, bb);
    if (borderBottom)
        renderBorderEdge(view, BOTTOM,
                         style->borderBottomStyle.getValue(),
                         style->borderBottomColor.getARGB(),
                         lr, bt, rl, bt, rr, bb, ll, bb);
    if (borderLeft)
        renderBorderEdge(view, LEFT,
                         style->borderLeftStyle.getValue(),
                         style->borderLeftColor.getARGB(),
                         ll, bb, ll, tt, lr, tb, lr, bt);
    glEnable(GL_TEXTURE_2D);
}

void BlockLevelBox::render(ViewCSSImp* view)
{
    glPushMatrix();
    glTranslatef(offsetH, offsetV, 0.0f);
    getOriginScreenPosition(x, y);
    renderBorder(view);
    glTranslatef(getBlankLeft(), getBlankTop(), 0.0f);
    if (shadow)
        shadow->render();
    else {
        for (auto child = getFirstChild(); child; child = child->getNextSibling()) {
            child->render(view);
            glTranslatef(0.0f, child->getTotalHeight(), 0.0f);
        }
    }
    glPopMatrix();
}

void LineBox::render(ViewCSSImp* view)
{
    glPushMatrix();
    glTranslatef(offsetH, offsetV, 0.0f);
    getOriginScreenPosition(x, y);
    for (auto child = getFirstChild(); child; child = child->getNextSibling()) {
        child->render(view);
        if (!child->isAbsolutelyPositioned()) {
            glTranslatef(child->getTotalWidth(), 0.0f, 0.0f);
        }
    }
    glPopMatrix();
}

void InlineLevelBox::render(ViewCSSImp* view)
{
    glPushMatrix();
    glTranslatef(offsetH, offsetV, 0.0f);
    renderBorder(view);
    glTranslatef(getBlankLeft(), getBlankTop(), 0.0f);
    getOriginScreenPosition(x, y);
    if (shadow)
        shadow->render();
    else if (getFirstChild())  // for inline-block
        getFirstChild()->render(view);
    else if (0 < data.length()) {
        glTranslatef(0.0f, baseline, 0.0f);
        glScalef(point / font->getPoint(), point / font->getPoint(), 1.0);
        unsigned color = getStyle()->color.getARGB();
        glColor4ub(color >> 16, color >> 8, color, color >> 24);
        font->renderText(data.c_str(), data.length());
    }
    glPopMatrix();
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(Box::renderBorder) : Paint the background of the render tree root box correctly.<commit_after>/*
 * Copyright 2010, 2011 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Box.h"

#include <GL/gl.h>
#include <GL/glu.h>

#include <stdio.h>

#include "CSSStyleDeclarationImp.h"
#include "ViewCSSImp.h"

#include "font/FontManager.h"
#include "font/FontManagerBackEndGL.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

namespace {

enum
{
    TOP,
    RIGHT,
    BOTTOM,
    LEFT
};

std::map<uint8_t*, GLuint> texnames;

GLuint addImage(uint8_t* image, unsigned width, unsigned heigth, unsigned repeat, GLenum format)
{
    GLuint texname;

    glGenTextures(1, &texname);
    glBindTexture(GL_TEXTURE_2D, texname);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (repeat & BoxImage::RepeatS) ? GL_REPEAT : (repeat & BoxImage::Clamp) ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (repeat & BoxImage::RepeatT) ? GL_REPEAT : (repeat & BoxImage::Clamp) ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, heigth, 0, format, GL_UNSIGNED_BYTE, image);
    texnames.insert(std::pair<uint8_t*, GLuint>(image, texname));
    return texname;
}

GLuint getTexname(uint8_t* image, unsigned width, unsigned height, unsigned repeat, GLenum format)
{
    std::map<uint8_t*, GLuint>::iterator it = texnames.find(image);
    if (it == texnames.end())
        return addImage(image, width, height, repeat, format);
    return it->second;
}

void deleteImage(uint8_t* image)
{
    std::map<uint8_t*, GLuint>::iterator it = texnames.find(image);
    if (it != texnames.end()) {
        glDeleteTextures(1, &it->second);
        texnames.erase(it);
    }
}

void getOriginScreenPosition(float& x, float& y)
{
    GLfloat m[16];
    glGetFloatv(GL_MODELVIEW_MATRIX, m);
    x = m[12];
    y = glutGet(GLUT_WINDOW_HEIGHT) - m[13];
}

}  // namespace

BoxImage::~BoxImage()
{
    if (state == CompletelyAvailable)
        deleteImage(pixels);
    delete pixels;
}

void BoxImage::render(ViewCSSImp* view, float x, float y, float width, float height, float left, float top)
{
    if (state != CompletelyAvailable)
        return;

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    if (repeat & BoxImage::Clamp)
        glScalef(1.0f / width, 1.0f / height, 0.0f);
    else
        glScalef(1.0f / naturalWidth, 1.0f / naturalHeight, 0.0f);
    glMatrixMode(GL_MODELVIEW);

    GLuint texname = getTexname(pixels, naturalWidth, naturalHeight, repeat, format);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, texname);
    glColor3ub(255, 255, 255);
    glBegin(GL_QUADS);
            glTexCoord2f(x - left, y - top);
            glVertex2f(x, y);
            glTexCoord2f(x - left + width, y - top);
            glVertex2f(x + width, y);
            glTexCoord2f(x - left + width, y - top + height);
            glVertex2f(x + width, y + height);
            glTexCoord2f(x - left, y - top + height);
            glVertex2f(x, y + height);
    glEnd();
    glDisable(GL_TEXTURE_2D);
}

void Box::renderBorderEdge(ViewCSSImp* view, int edge, unsigned borderStyle, unsigned color,
                           float a, float b, float c, float d,
                           float e, float f, float g, float h)
{
    if (borderStyle == CSSBorderStyleValueImp::None ||
        borderStyle == CSSBorderStyleValueImp::Hidden)
        return;

    GLubyte red = color >> 16;
    GLubyte green = color >> 8;
    GLubyte blue = color;
    GLubyte alpha = color >> 24;

    if (borderStyle == CSSBorderStyleValueImp::Double) {
        float offset;
        offset = (g - a) / 3;
        float i = a + offset;
        float m = g - offset;
        offset = (h - b) / 3;
        float j = b + offset;
        float n = h - offset;
        offset = (c - e) / 3;
        float k = c - offset;
        float o = e + offset;
        offset = (f - d) / 3;
        float l = d + offset;
        float p = f - offset;
        glColor4ub(red, green, blue, alpha);
        glBegin(GL_QUADS);
            glVertex2f(a, b);
            glVertex2f(c, d);
            glVertex2f(k, l);
            glVertex2f(i, j);
        glEnd();
        glBegin(GL_QUADS);
            glVertex2f(m, n);
            glVertex2f(o, p);
            glVertex2f(e, f);
            glVertex2f(g, h);
        glEnd();
        return;
    }

    if (borderStyle == CSSBorderStyleValueImp::Dotted ||
        borderStyle == CSSBorderStyleValueImp::Dashed) {
        glEnable(GL_LINE_STIPPLE);
        glLineWidth(fabsf(g - a));
        glLineStipple(fabsf(g - a), (borderStyle == CSSBorderStyleValueImp::Dotted) ? 0xaaaa : 0xcccc);
        glBegin(GL_LINES);
            glColor4ub(red, green, blue, alpha);
            glVertex2f((a + g) / 2, (b + h) / 2);
            glVertex2f((c + e) / 2, (d + f) / 2);
        glEnd();
        glDisable(GL_LINE_STIPPLE);
        return;
    }

    if (borderStyle == CSSBorderStyleValueImp::Groove ||
        borderStyle == CSSBorderStyleValueImp::Ridge) {
        GLubyte redDark = std::max(red - 128, 0);
        GLubyte greenDark = std::max(green - 128, 0);
        GLubyte blueDark = std::max(blue - 128, 0);
        GLubyte redBright = std::min(red + 128, 255);
        GLubyte greenBright = std::min(green + 128, 255);
        GLubyte blueBright = std::min(blue + 128, 255);
        float offset;
        offset = (g - a) / 2;
        float i = a + offset;
        offset = (h - b) / 2;
        float j = b + offset;
        offset = (c - e) / 2;
        float k = c - offset;
        offset = (f - d) / 2;
        float l = d + offset;
        if (borderStyle == CSSBorderStyleValueImp::Groove)
            glColor4ub(redDark, greenDark, blueDark, alpha);
        else
            glColor4ub(redBright, greenBright, blueBright, alpha);
        glBegin(GL_QUADS);
            glVertex2f(a, b);
            glVertex2f(c, d);
            glVertex2f(k, l);
            glVertex2f(i, j);
        glEnd();
        if (borderStyle == CSSBorderStyleValueImp::Groove)
            glColor4ub(redBright, greenBright, blueBright, alpha);
        else
            glColor4ub(redDark, greenDark, blueDark, alpha);
        glBegin(GL_QUADS);
            glVertex2f(i, j);
            glVertex2f(k, l);
            glVertex2f(e, f);
            glVertex2f(g, h);
        glEnd();
        return;
    }

    if (borderStyle == CSSBorderStyleValueImp::Inset ||
        borderStyle == CSSBorderStyleValueImp::Outset) {
        bool dark = false;
        bool bright = false;
        if (borderStyle == CSSBorderStyleValueImp::Inset) {
            switch (edge) {
            case TOP:
            case LEFT:
                dark = true;
                break;;
            case RIGHT:
            case BOTTOM:
                bright = true;
                break;;
            }
        }
        if (borderStyle == CSSBorderStyleValueImp::Outset) {
            switch (edge) {
            case TOP:
            case LEFT:
                bright = true;
                break;;
            case RIGHT:
            case BOTTOM:
                dark = true;
                break;;
            }
        }
        if (dark) {
            red = std::max(red - 128, 0);
            green = std::max(green - 128, 0);
            blue = std::max(blue - 128, 0);
        } else if (bright) {
            red = std::min(red + 128, 255);
            green = std::min(green + 128, 255);
            blue = std::min(blue + 128, 255);
        }
    }

    glColor4ub(red, green, blue, alpha);
    glBegin(GL_QUADS);
        glVertex2f(a, b);
        glVertex2f(c, d);
        glVertex2f(e, f);
        glVertex2f(g, h);
    glEnd();
}

void Box::renderBorder(ViewCSSImp* view)
{
    glDisable(GL_TEXTURE_2D);

    float ll = marginLeft;
    float lr = ll + borderLeft;
    float rl = lr + paddingLeft + width + paddingRight;
    float rr = rl + borderRight;
    float tt = marginTop;
    float tb = tt + borderTop;
    float bt = tb + paddingTop + height + paddingBottom;
    float bb = bt + borderBottom;

    if (backgroundColor != 0x00000000) {
        glColor4ub(backgroundColor >> 16, backgroundColor >> 8, backgroundColor, backgroundColor >> 24);
        glBegin(GL_QUADS);
            if (getParentBox()) {
                glVertex2f(lr, tb);
                glVertex2f(rl, tb);
                glVertex2f(rl, bt);
                glVertex2f(lr, bt);
            } else {
                const ContainingBlock* containingBlock = getContainingBlock(view);
                glVertex2f(0, 0);
                glVertex2f(containingBlock->width, 0);
                glVertex2f(containingBlock->width, containingBlock->height);
                glVertex2f(0, containingBlock->height);
            }
        glEnd();
    }

    if (backgroundImage) {
        GLfloat border[] = { ((backgroundColor >> 16) & 0xff) / 255.0f,
                             ((backgroundColor >> 8) & 0xff) / 255.0f,
                             ((backgroundColor) & 0xff) / 255.0f,
                             ((backgroundColor >> 24) & 0xff) / 255.0f };
        glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
        glPushMatrix();
        if (getParentBox()) {
            // TODO: check padding
            glTranslatef(lr, tb, 0.0f);
            backgroundImage->render(view, 0, 0, rl - lr, bt - tb, backgroundLeft, backgroundTop);
        } else {
            const ContainingBlock* containingBlock = getContainingBlock(view);
            glTranslatef(ll, tt, 0.0f);
            backgroundImage->render(view, -ll, -tt, containingBlock->width, containingBlock->height, backgroundLeft, backgroundTop);
        }
        glPopMatrix();
    }

    if (borderTop)
        renderBorderEdge(view, TOP,
                         style->borderTopStyle.getValue(),
                         style->borderTopColor.getARGB(),
                         ll, tt, rr, tt, rl, tb, lr, tb);
    if (borderRight)
        renderBorderEdge(view, RIGHT,
                         style->borderRightStyle.getValue(),
                         style->borderRightColor.getARGB(),
                         rl, bt, rl, tb, rr, tt, rr, bb);
    if (borderBottom)
        renderBorderEdge(view, BOTTOM,
                         style->borderBottomStyle.getValue(),
                         style->borderBottomColor.getARGB(),
                         lr, bt, rl, bt, rr, bb, ll, bb);
    if (borderLeft)
        renderBorderEdge(view, LEFT,
                         style->borderLeftStyle.getValue(),
                         style->borderLeftColor.getARGB(),
                         ll, bb, ll, tt, lr, tb, lr, bt);
    glEnable(GL_TEXTURE_2D);
}

void BlockLevelBox::render(ViewCSSImp* view)
{
    glPushMatrix();
    glTranslatef(offsetH, offsetV, 0.0f);
    getOriginScreenPosition(x, y);
    renderBorder(view);
    glTranslatef(getBlankLeft(), getBlankTop(), 0.0f);
    if (shadow)
        shadow->render();
    else {
        for (auto child = getFirstChild(); child; child = child->getNextSibling()) {
            child->render(view);
            glTranslatef(0.0f, child->getTotalHeight(), 0.0f);
        }
    }
    glPopMatrix();
}

void LineBox::render(ViewCSSImp* view)
{
    glPushMatrix();
    glTranslatef(offsetH, offsetV, 0.0f);
    getOriginScreenPosition(x, y);
    for (auto child = getFirstChild(); child; child = child->getNextSibling()) {
        child->render(view);
        if (!child->isAbsolutelyPositioned()) {
            glTranslatef(child->getTotalWidth(), 0.0f, 0.0f);
        }
    }
    glPopMatrix();
}

void InlineLevelBox::render(ViewCSSImp* view)
{
    glPushMatrix();
    glTranslatef(offsetH, offsetV, 0.0f);
    renderBorder(view);
    glTranslatef(getBlankLeft(), getBlankTop(), 0.0f);
    getOriginScreenPosition(x, y);
    if (shadow)
        shadow->render();
    else if (getFirstChild())  // for inline-block
        getFirstChild()->render(view);
    else if (0 < data.length()) {
        glTranslatef(0.0f, baseline, 0.0f);
        glScalef(point / font->getPoint(), point / font->getPoint(), 1.0);
        unsigned color = getStyle()->color.getARGB();
        glColor4ub(color >> 16, color >> 8, color, color >> 24);
        font->renderText(data.c_str(), data.length());
    }
    glPopMatrix();
}

}}}}  // org::w3c::dom::bootstrap
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// For information about interceptions as a whole see
// http://wiki/Main/ChromeSandboxInterceptionDesign

#include "sandbox/src/interception_agent.h"

#include "sandbox/src/interception_internal.h"
#include "sandbox/src/eat_resolver.h"
#include "sandbox/src/sidestep_resolver.h"
#include "sandbox/src/sandbox_nt_util.h"

namespace {

// Returns true if target lies between base and base + range.
bool IsWithinRange(const void* base, size_t range, const void* target) {
  const char* end = reinterpret_cast<const char*>(base) + range;
  return reinterpret_cast<const char*>(target) < end;
}

}  // namespace

namespace sandbox {

// This is the list of all imported symbols from ntdll.dll.
SANDBOX_INTERCEPT NtExports g_nt;

// Memory buffer mapped from the parent, with the list of interceptions.
SANDBOX_INTERCEPT SharedMemory* g_interceptions = NULL;

InterceptionAgent* InterceptionAgent::GetInterceptionAgent() {
  static InterceptionAgent* s_singleton_pointer = NULL;
  if (!s_singleton_pointer) {
    if (!g_interceptions)
      return NULL;

    size_t object_bytes = g_interceptions->num_intercepted_dlls * sizeof(void*);
    s_singleton_pointer = reinterpret_cast<InterceptionAgent*>(
                              new(NT_ALLOC) char[object_bytes]);

    bool success = s_singleton_pointer->Init(g_interceptions);
    if (!success) {
      operator delete(s_singleton_pointer, NT_ALLOC);
      s_singleton_pointer = NULL;
    }
  }
  return s_singleton_pointer;
}

bool InterceptionAgent::Init(SharedMemory* shared_memory) {
  interceptions_ = shared_memory;
  for (int i = 0 ; i < shared_memory->num_intercepted_dlls; i++)
    dlls_[i] = NULL;
  return true;
}

bool InterceptionAgent::DllMatch(const UNICODE_STRING* full_path,
                                 const UNICODE_STRING* name,
                                 const DllPatchInfo* dll_info) {
  UNICODE_STRING current_name;
  current_name.Length = static_cast<USHORT>(g_nt.wcslen(dll_info->dll_name) *
                                            sizeof(wchar_t));
  current_name.MaximumLength = current_name.Length;
  current_name.Buffer = const_cast<wchar_t*>(dll_info->dll_name);

  BOOLEAN case_insensitive = TRUE;
  if (full_path &&
      !g_nt.RtlCompareUnicodeString(&current_name, full_path, case_insensitive))
    return true;

  if (!g_nt.RtlCompareUnicodeString(&current_name, name, case_insensitive))
    return true;

  return false;
}

void InterceptionAgent::OnDllLoad(const UNICODE_STRING* full_path,
                                  const UNICODE_STRING* name,
                                  void* base_address) {
  DllPatchInfo* dll_info = interceptions_->dll_list;
  int i = 0;
  for (; i < interceptions_->num_intercepted_dlls; i++) {
    if (DllMatch(full_path, name, dll_info))
      break;

    dll_info = reinterpret_cast<DllPatchInfo*>(
                   reinterpret_cast<char*>(dll_info) + dll_info->record_bytes);
  }
  if (i == interceptions_->num_intercepted_dlls)
    return;

  // Purify causes this condition to trigger.
  if (dlls_[i])
    return;

  size_t buffer_bytes = offsetof(DllInterceptionData, thunks) +
                        dll_info->num_functions * sizeof(ThunkData);
  dlls_[i] = reinterpret_cast<DllInterceptionData*>(
                 new(NT_PAGE) char[buffer_bytes]);

  DCHECK_NT(dlls_[i]);
  if (!dlls_[i])
    return;

  dlls_[i]->data_bytes = buffer_bytes;
  dlls_[i]->num_thunks = 0;
  dlls_[i]->base = base_address;
  dlls_[i]->used_bytes = offsetof(DllInterceptionData, thunks);

  VERIFY(PatchDll(dll_info, dlls_[i]));

  ULONG old_protect;
  SIZE_T real_size = buffer_bytes;
  void* to_protect = dlls_[i];
  VERIFY_SUCCESS(g_nt.ProtectVirtualMemory(NtCurrentProcess, &to_protect,
                                           &real_size, PAGE_EXECUTE_READ,
                                           &old_protect));
}

void InterceptionAgent::OnDllUnload(void* base_address) {
  for (int i = 0; i < interceptions_->num_intercepted_dlls; i++) {
    if (dlls_[i] && dlls_[i]->base == base_address) {
      operator delete(dlls_[i], NT_PAGE);
      dlls_[i] = NULL;
      break;
    }
  }
}

// TODO(rvargas): We have to deal with prebinded dlls. I see two options: change
// the timestamp of the patched dll, or modify the info on the prebinded dll.
// the first approach messes matching of debug symbols, the second one is more
// complicated.
bool InterceptionAgent::PatchDll(const DllPatchInfo* dll_info,
                                 DllInterceptionData* thunks) {
  DCHECK_NT(NULL != thunks);
  DCHECK_NT(NULL != dll_info);

  const FunctionInfo* function = reinterpret_cast<const FunctionInfo*>(
      reinterpret_cast<const char*>(dll_info) + dll_info->offset_to_functions);

  for (int i = 0; i < dll_info->num_functions; i++) {
    if (!IsWithinRange(dll_info, dll_info->record_bytes, function->function)) {
      NOTREACHED_NT();
      return false;
    }

    ResolverThunk* resolver = GetResolver(function->type);
    if (!resolver)
      return false;

    const char* interceptor = function->function +
                              g_nt.strlen(function->function) + 1;

    if (!IsWithinRange(function, function->record_bytes, interceptor) ||
        !IsWithinRange(dll_info, dll_info->record_bytes, interceptor)) {
      NOTREACHED_NT();
      return false;
    }

    NTSTATUS ret = resolver->Setup(thunks->base,
                                   interceptions_->interceptor_base,
                                   function->function,
                                   interceptor,
                                   function->interceptor_address,
                                   &thunks->thunks[i],
                                   sizeof(ThunkData),
                                   NULL);
    if (!NT_SUCCESS(ret)) {
      NOTREACHED_NT();
      return false;
    }

    thunks->num_thunks++;
    thunks->used_bytes += sizeof(ThunkData);

    function = reinterpret_cast<const FunctionInfo*>(
        reinterpret_cast<const char*>(function) + function->record_bytes);
  }

  return true;
}

// This method is called from within the loader lock
ResolverThunk* InterceptionAgent::GetResolver(InterceptionType type) {
  static EatResolverThunk* eat_resolver = NULL;
  static SidestepResolverThunk* sidestep_resolver = NULL;
  static SmartSidestepResolverThunk* smart_sidestep_resolver = NULL;

  if (!eat_resolver)
    eat_resolver = new(NT_ALLOC) EatResolverThunk;

  if (!sidestep_resolver)
    sidestep_resolver = new(NT_ALLOC) SidestepResolverThunk;

  if (!smart_sidestep_resolver)
    smart_sidestep_resolver = new(NT_ALLOC) SmartSidestepResolverThunk;

  switch (type) {
    case INTERCEPTION_EAT:
      return eat_resolver;
    case INTERCEPTION_SIDESTEP:
      return sidestep_resolver;
    case INTERCEPTION_SMART_SIDESTEP:
      return smart_sidestep_resolver;
    default:
      NOTREACHED_NT();
  }

  return NULL;
}

}  // namespace sandbox

<commit_msg>Fix memory corruption when EAT patching in sandbox<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// For information about interceptions as a whole see
// http://wiki/Main/ChromeSandboxInterceptionDesign

#include "sandbox/src/interception_agent.h"

#include "sandbox/src/interception_internal.h"
#include "sandbox/src/eat_resolver.h"
#include "sandbox/src/sidestep_resolver.h"
#include "sandbox/src/sandbox_nt_util.h"

namespace {

// Returns true if target lies between base and base + range.
bool IsWithinRange(const void* base, size_t range, const void* target) {
  const char* end = reinterpret_cast<const char*>(base) + range;
  return reinterpret_cast<const char*>(target) < end;
}

}  // namespace

namespace sandbox {

// This is the list of all imported symbols from ntdll.dll.
SANDBOX_INTERCEPT NtExports g_nt;

// Memory buffer mapped from the parent, with the list of interceptions.
SANDBOX_INTERCEPT SharedMemory* g_interceptions = NULL;

InterceptionAgent* InterceptionAgent::GetInterceptionAgent() {
  static InterceptionAgent* s_singleton = NULL;
  if (!s_singleton) {
    if (!g_interceptions)
      return NULL;

    size_t array_bytes = g_interceptions->num_intercepted_dlls * sizeof(void*);
    s_singleton = reinterpret_cast<InterceptionAgent*>(
        new(NT_ALLOC) char[array_bytes + sizeof(InterceptionAgent)]);

    bool success = s_singleton->Init(g_interceptions);
    if (!success) {
      operator delete(s_singleton, NT_ALLOC);
      s_singleton = NULL;
    }
  }
  return s_singleton;
}

bool InterceptionAgent::Init(SharedMemory* shared_memory) {
  interceptions_ = shared_memory;
  for (int i = 0 ; i < shared_memory->num_intercepted_dlls; i++)
    dlls_[i] = NULL;
  return true;
}

bool InterceptionAgent::DllMatch(const UNICODE_STRING* full_path,
                                 const UNICODE_STRING* name,
                                 const DllPatchInfo* dll_info) {
  UNICODE_STRING current_name;
  current_name.Length = static_cast<USHORT>(g_nt.wcslen(dll_info->dll_name) *
                                            sizeof(wchar_t));
  current_name.MaximumLength = current_name.Length;
  current_name.Buffer = const_cast<wchar_t*>(dll_info->dll_name);

  BOOLEAN case_insensitive = TRUE;
  if (full_path &&
      !g_nt.RtlCompareUnicodeString(&current_name, full_path, case_insensitive))
    return true;

  if (!g_nt.RtlCompareUnicodeString(&current_name, name, case_insensitive))
    return true;

  return false;
}

void InterceptionAgent::OnDllLoad(const UNICODE_STRING* full_path,
                                  const UNICODE_STRING* name,
                                  void* base_address) {
  DllPatchInfo* dll_info = interceptions_->dll_list;
  int i = 0;
  for (; i < interceptions_->num_intercepted_dlls; i++) {
    if (DllMatch(full_path, name, dll_info))
      break;

    dll_info = reinterpret_cast<DllPatchInfo*>(
                   reinterpret_cast<char*>(dll_info) + dll_info->record_bytes);
  }
  if (i == interceptions_->num_intercepted_dlls)
    return;

  // Purify causes this condition to trigger.
  if (dlls_[i])
    return;

  size_t buffer_bytes = offsetof(DllInterceptionData, thunks) +
                        dll_info->num_functions * sizeof(ThunkData);
  dlls_[i] = reinterpret_cast<DllInterceptionData*>(
                 new(NT_PAGE) char[buffer_bytes]);

  DCHECK_NT(dlls_[i]);
  if (!dlls_[i])
    return;

  dlls_[i]->data_bytes = buffer_bytes;
  dlls_[i]->num_thunks = 0;
  dlls_[i]->base = base_address;
  dlls_[i]->used_bytes = offsetof(DllInterceptionData, thunks);

  VERIFY(PatchDll(dll_info, dlls_[i]));

  ULONG old_protect;
  SIZE_T real_size = buffer_bytes;
  void* to_protect = dlls_[i];
  VERIFY_SUCCESS(g_nt.ProtectVirtualMemory(NtCurrentProcess, &to_protect,
                                           &real_size, PAGE_EXECUTE_READ,
                                           &old_protect));
}

void InterceptionAgent::OnDllUnload(void* base_address) {
  for (int i = 0; i < interceptions_->num_intercepted_dlls; i++) {
    if (dlls_[i] && dlls_[i]->base == base_address) {
      operator delete(dlls_[i], NT_PAGE);
      dlls_[i] = NULL;
      break;
    }
  }
}

// TODO(rvargas): We have to deal with prebinded dlls. I see two options: change
// the timestamp of the patched dll, or modify the info on the prebinded dll.
// the first approach messes matching of debug symbols, the second one is more
// complicated.
bool InterceptionAgent::PatchDll(const DllPatchInfo* dll_info,
                                 DllInterceptionData* thunks) {
  DCHECK_NT(NULL != thunks);
  DCHECK_NT(NULL != dll_info);

  const FunctionInfo* function = reinterpret_cast<const FunctionInfo*>(
      reinterpret_cast<const char*>(dll_info) + dll_info->offset_to_functions);

  for (int i = 0; i < dll_info->num_functions; i++) {
    if (!IsWithinRange(dll_info, dll_info->record_bytes, function->function)) {
      NOTREACHED_NT();
      return false;
    }

    ResolverThunk* resolver = GetResolver(function->type);
    if (!resolver)
      return false;

    const char* interceptor = function->function +
                              g_nt.strlen(function->function) + 1;

    if (!IsWithinRange(function, function->record_bytes, interceptor) ||
        !IsWithinRange(dll_info, dll_info->record_bytes, interceptor)) {
      NOTREACHED_NT();
      return false;
    }

    NTSTATUS ret = resolver->Setup(thunks->base,
                                   interceptions_->interceptor_base,
                                   function->function,
                                   interceptor,
                                   function->interceptor_address,
                                   &thunks->thunks[i],
                                   sizeof(ThunkData),
                                   NULL);
    if (!NT_SUCCESS(ret)) {
      NOTREACHED_NT();
      return false;
    }

    thunks->num_thunks++;
    thunks->used_bytes += sizeof(ThunkData);

    function = reinterpret_cast<const FunctionInfo*>(
        reinterpret_cast<const char*>(function) + function->record_bytes);
  }

  return true;
}

// This method is called from within the loader lock
ResolverThunk* InterceptionAgent::GetResolver(InterceptionType type) {
  static EatResolverThunk* eat_resolver = NULL;
  static SidestepResolverThunk* sidestep_resolver = NULL;
  static SmartSidestepResolverThunk* smart_sidestep_resolver = NULL;

  if (!eat_resolver)
    eat_resolver = new(NT_ALLOC) EatResolverThunk;

  if (!sidestep_resolver)
    sidestep_resolver = new(NT_ALLOC) SidestepResolverThunk;

  if (!smart_sidestep_resolver)
    smart_sidestep_resolver = new(NT_ALLOC) SmartSidestepResolverThunk;

  switch (type) {
    case INTERCEPTION_EAT:
      return eat_resolver;
    case INTERCEPTION_SIDESTEP:
      return sidestep_resolver;
    case INTERCEPTION_SMART_SIDESTEP:
      return smart_sidestep_resolver;
    default:
      NOTREACHED_NT();
  }

  return NULL;
}

}  // namespace sandbox

<|endoftext|>