<commit_before>//
//  src/recursive/mkdir.cc
//  tbd
//
//  Created by inoahdev on 10/15/17.
//  Copyright © 2017 - 2018 inoahdev. All rights reserved.
//

#include <cerrno>
#include <sys/stat.h>

#include <fcntl.h>
#include <unistd.h>

#include "../utils/path.h"
#include "mkdir.h"

namespace recursive::mkdir {
    inline bool _create_directory(char *path) noexcept {
        return ::mkdir(path, 0755) == 0;
    }

    inline result create_directories_ignoring_last(char *path, char *path_end, char *begin) noexcept {
        auto path_component_end = begin;

        do {
            auto next_path_component_begin = utils::path::find_end_of_row_of_slashes(path_component_end, path_end);
            if (next_path_component_begin == path_end) {
                break;
            }

            auto path_component_end_elmt = *path_component_end;
            *path_component_end = '\0';

            if (!_create_directory(path)) {
                return result::failed_to_create_intermediate_directories;
            }

            *path_component_end = path_component_end_elmt;
            path_component_end = utils::path::find_next_slash(next_path_component_begin, path_end);
        } while (true);

        return result::ok;
    }

    result create_directories_if_missing_ignoring_last(char *path, char **terminator) noexcept {
        auto end = utils::string::find_end_of_null_terminated_string(path);
        auto &back = end[-1];

        // In the case where path ends with a series of slashes
        // set end to the front most slash in that series

        if (back == '/' || back == '\\') {
            end = utils::path::find_last_slash_in_front_of_pattern(path, end);
        }

        // Start from second-to-last path-component, as we
        // are after all, ignoring the last path-component

        auto path_component_end = utils::path::find_last_slash_in_front_of_pattern(path, end);
        auto prev_path_component_end = end;

        // Walk backwards, from the second-to-last
        // path-component, all the way back to the first

        // This is done in this way so as to minimize
        // syscalls on directories that most likely exist
        // (the first few path-components) versus those that
        // most likely don't exist (the last few path-components)

        while (path_component_end != path) {
            // Terminate string at path-component end,
            // so as to get the entire path of the current
            // path-component

            auto path_component_end_elmt = *path_component_end;
            *path_component_end = '\0';

            if (access(path, F_OK) == 0) {
                if (terminator != nullptr) {
                    *terminator = prev_path_component_end;

                    // terminator should never point to
                    // end because terminator is used in
                    // recursively-remove which does not
                    // check this

                    if (*terminator == end) {
                        *terminator = nullptr;
                    }
                }

                *path_component_end = path_component_end_elmt;
                return create_directories_ignoring_last(path, end, prev_path_component_end);
            }

            prev_path_component_end = path_component_end;
            path_component_end = utils::path::find_last_slash_in_front_of_pattern(path, path_component_end);

            *prev_path_component_end = path_component_end_elmt;
        }

        return result::ok;
    }

    result perform(char *path, char **terminator) noexcept {
        if (const auto result = create_directories_if_missing_ignoring_last(path, terminator); result != result::ok) {
            return result;
        }

        if (!_create_directory(path)) {
            if (errno == EEXIST) {
                return result::ok;
            }

            return result::failed_to_create_last_as_directory;
        }

        return result::ok;
    }

    result perform_ignorning_last(char *path, char **terminator) noexcept {
        return create_directories_if_missing_ignoring_last(path, terminator);
    }

    result perform_with_last_as_file(char *path, char **terminator, int *last_descriptor) noexcept {
        if (const auto result = create_directories_if_missing_ignoring_last(path, terminator); result != result::ok) {
            return result;
        }

        const auto descriptor = open(path, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE);
        if (descriptor == -1) {
            if (errno == EEXIST) {
                return result::ok;
            }

            return result::failed_to_create_last_as_file;
        }

        if (last_descriptor != nullptr) {
            *last_descriptor = descriptor;
        } else {
            close(descriptor);
        }

        return result::ok;
    }
}
<commit_msg>Fix bugs surrounding implementation of terminator in recursive-mkdir<commit_after>//
//  src/recursive/mkdir.cc
//  tbd
//
//  Created by inoahdev on 10/15/17.
//  Copyright © 2017 - 2018 inoahdev. All rights reserved.
//

#include <cerrno>
#include <sys/stat.h>

#include <fcntl.h>
#include <unistd.h>

#include "../utils/path.h"
#include "mkdir.h"

namespace recursive::mkdir {
    inline bool _create_directory(char *path) noexcept {
        return ::mkdir(path, 0755) == 0;
    }

    inline result create_directories_ignoring_last(char *path, char *path_end, char *begin) noexcept {
        auto path_component_end = begin;

        do {
            auto next_path_component_begin = utils::path::find_end_of_row_of_slashes(path_component_end, path_end);
            if (next_path_component_begin == path_end) {
                break;
            }

            auto path_component_end_chr = *path_component_end;
            *path_component_end = '\0';

            if (!_create_directory(path)) {
                return result::failed_to_create_intermediate_directories;
            }

            *path_component_end = path_component_end_chr;
            path_component_end = utils::path::find_next_slash(next_path_component_begin, path_end);
        } while (true);

        return result::ok;
    }

    result create_directories_if_missing_ignoring_last(char *path, char **terminator) noexcept {
        auto end = utils::string::find_end_of_null_terminated_string(path);
        auto &back = end[-1];

        // In the case where path ends with a series of slashes
        // set end to the front most slash in that series

        if (back == '/' || back == '\\') {
            end = utils::path::find_last_slash_in_front_of_pattern(path, end);
        }

        // Start from second-to-last path-component, as we
        // are after all, ignoring the last path-component

        auto path_component_end = utils::path::find_last_slash_in_front_of_pattern(path, end);
        auto prev_path_component_end = end;

        // Walk backwards, from the second-to-last
        // path-component, all the way back to the first

        // This is done in this way so as to minimize
        // syscalls on directories that most likely exist
        // (the first few path-components) versus those that
        // most likely don't exist (the last few path-components)

        while (path_component_end != path) {
            // Terminate string at path-component end,
            // so as to get the entire path of the current
            // path-component

            auto path_component_end_chr = *path_component_end;
            *path_component_end = '\0';

            if (access(path, F_OK) == 0) {
                // if prev_path_component_end points
                // to end,it means we are at the first
                // path component, and all path-components,
                // save the last, which we are to ignore
                // exist

                if (prev_path_component_end == end) {
                    *path_component_end = '/';
                    break;
                }

                if (terminator != nullptr) {
                    *terminator = prev_path_component_end;
                }

                *path_component_end = path_component_end_chr;
                return create_directories_ignoring_last(path, end, prev_path_component_end);
            }

            prev_path_component_end = path_component_end;
            path_component_end = utils::path::find_last_slash_in_front_of_pattern(path, path_component_end);

            *prev_path_component_end = path_component_end_chr;
        }

        return result::ok;
    }

    result perform(char *path, char **terminator) noexcept {
        if (const auto result = create_directories_if_missing_ignoring_last(path, terminator); result != result::ok) {
            return result;
        }

        const auto result = _create_directory(path);
        if (result || (!result && errno == EEXIST)) {
            if (terminator != nullptr) {
                if (*terminator == nullptr) {
                    *terminator = utils::string::find_end_of_null_terminated_string(path);
                }
            }

            return result::ok;
        }

        return result::failed_to_create_last_as_directory;
    }

    result perform_ignorning_last(char *path, char **terminator) noexcept {
        return create_directories_if_missing_ignoring_last(path, terminator);
    }

    result perform_with_last_as_file(char *path, char **terminator, int *last_descriptor) noexcept {
        if (const auto result = create_directories_if_missing_ignoring_last(path, terminator); result != result::ok) {
            return result;
        }

        const auto descriptor = open(path, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE);
        if (descriptor == -1) {
            if (errno == EEXIST) {
                return result::ok;
            }

            return result::failed_to_create_last_as_file;
        }

        if (terminator != nullptr) {
            if (*terminator == nullptr) {
                *terminator = utils::string::find_end_of_null_terminated_string(path);
            }
        }

        if (last_descriptor != nullptr) {
            *last_descriptor = descriptor;
        } else {
            close(descriptor);
        }

        return result::ok;
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2011-2013 Blender Foundation
 *
 * 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 <stdlib.h>

#include "buffers.h"
#include "device.h"

#include "util_debug.h"
#include "util_foreach.h"
#include "util_hash.h"
#include "util_image.h"
#include "util_math.h"
#include "util_opengl.h"
#include "util_time.h"
#include "util_types.h"

CCL_NAMESPACE_BEGIN

/* Buffer Params */

BufferParams::BufferParams()
{
	width = 0;
	height = 0;

	full_x = 0;
	full_y = 0;
	full_width = 0;
	full_height = 0;

	Pass::add(PASS_COMBINED, passes);
}

void BufferParams::get_offset_stride(int& offset, int& stride)
{
	offset = -(full_x + full_y*width);
	stride = width;
}

bool BufferParams::modified(const BufferParams& params)
{
	return !(full_x == params.full_x
		&& full_y == params.full_y
		&& width == params.width
		&& height == params.height
		&& full_width == params.full_width
		&& full_height == params.full_height
		&& Pass::equals(passes, params.passes));
}

int BufferParams::get_passes_size()
{
	int size = 0;

	for(size_t i = 0; i < passes.size(); i++)
		size += passes[i].components;

	return align_up(size, 4);
}

/* Render Buffer Task */

RenderTile::RenderTile()
{
	x = 0;
	y = 0;
	w = 0;
	h = 0;

	sample = 0;
	start_sample = 0;
	num_samples = 0;
	resolution = 0;

	offset = 0;
	stride = 0;

	buffer = 0;
	rng_state = 0;

	buffers = NULL;
}

/* Render Buffers */

RenderBuffers::RenderBuffers(Device *device_)
{
	device = device_;
}

RenderBuffers::~RenderBuffers()
{
	device_free();
}

void RenderBuffers::device_free()
{
	if(buffer.device_pointer) {
		device->mem_free(buffer);
		buffer.clear();
	}

	if(rng_state.device_pointer) {
		device->mem_free(rng_state);
		rng_state.clear();
	}
}

void RenderBuffers::reset(Device *device, BufferParams& params_)
{
	params = params_;

	/* free existing buffers */
	device_free();

	/* allocate buffer */
	buffer.resize(params.width*params.height*params.get_passes_size());
	device->mem_alloc(buffer, MEM_READ_WRITE);
	device->mem_zero(buffer);

	/* allocate rng state */
	rng_state.resize(params.width, params.height);

	device->mem_alloc(rng_state, MEM_READ_WRITE);
}

bool RenderBuffers::copy_from_device()
{
	if(!buffer.device_pointer)
		return false;

	device->mem_copy_from(buffer, 0, params.width, params.height, params.get_passes_size()*sizeof(float));

	return true;
}

bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels)
{
	int pass_offset = 0;

	for(size_t j = 0; j < params.passes.size(); j++) {
		Pass& pass = params.passes[j];

		if(pass.type != type) {
			pass_offset += pass.components;
			continue;
		}

		float *in = (float*)buffer.data_pointer + pass_offset;
		int pass_stride = params.get_passes_size();

		float scale = (pass.filter)? 1.0f/(float)sample: 1.0f;
		float scale_exposure = (pass.exposure)? scale*exposure: scale;

		int size = params.width*params.height;

		if(components == 1) {
			assert(pass.components == components);

			/* scalar */
			if(type == PASS_DEPTH) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
					float f = *in;
					pixels[0] = (f == 0.0f)? 1e10f: f*scale_exposure;
				}
			}
			else if(type == PASS_MIST) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
					float f = *in;
					pixels[0] = saturate(f*scale_exposure);
				}
			}
#ifdef WITH_CYCLES_DEBUG
			else if(type == PASS_BVH_TRAVERSAL_STEPS) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
					float f = *in;
					pixels[0] = f*scale;
				}
			}
			else if(type == PASS_RAY_BOUNCES) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
					float f = *in;
					pixels[0] = f*scale;
				}
			}
#endif
			else {
				for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
					float f = *in;
					pixels[0] = f*scale_exposure;
				}
			}
		}
		else if(components == 3) {
			assert(pass.components == 4);

			/* RGBA */
			if(type == PASS_SHADOW) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
					float4 f = make_float4(in[0], in[1], in[2], in[3]);
					float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;

					pixels[0] = f.x*invw;
					pixels[1] = f.y*invw;
					pixels[2] = f.z*invw;
				}
			}
			else if(pass.divide_type != PASS_NONE) {
				/* RGB lighting passes that need to divide out color */
				pass_offset = 0;
				for(size_t k = 0; k < params.passes.size(); k++) {
					Pass& color_pass = params.passes[k];
					if(color_pass.type == pass.divide_type)
						break;
					pass_offset += color_pass.components;
				}

				float *in_divide = (float*)buffer.data_pointer + pass_offset;

				for(int i = 0; i < size; i++, in += pass_stride, in_divide += pass_stride, pixels += 3) {
					float3 f = make_float3(in[0], in[1], in[2]);
					float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]);

					f = safe_divide_even_color(f*exposure, f_divide);

					pixels[0] = f.x;
					pixels[1] = f.y;
					pixels[2] = f.z;
				}
			}
			else {
				/* RGB/vector */
				for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
					float3 f = make_float3(in[0], in[1], in[2]);

					pixels[0] = f.x*scale_exposure;
					pixels[1] = f.y*scale_exposure;
					pixels[2] = f.z*scale_exposure;
				}
			}
		}
		else if(components == 4) {
			assert(pass.components == components);

			/* RGBA */
			if(type == PASS_SHADOW) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
					float4 f = make_float4(in[0], in[1], in[2], in[3]);
					float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;

					pixels[0] = f.x*invw;
					pixels[1] = f.y*invw;
					pixels[2] = f.z*invw;
					pixels[3] = 1.0f;
				}
			}
			else if(type == PASS_MOTION) {
				/* need to normalize by number of samples accumulated for motion */
				pass_offset = 0;
				for(size_t k = 0; k < params.passes.size(); k++) {
					Pass& color_pass = params.passes[k];
					if(color_pass.type == PASS_MOTION_WEIGHT)
						break;
					pass_offset += color_pass.components;
				}

				float *in_weight = (float*)buffer.data_pointer + pass_offset;

				for(int i = 0; i < size; i++, in += pass_stride, in_weight += pass_stride, pixels += 4) {
					float4 f = make_float4(in[0], in[1], in[2], in[3]);
					float w = in_weight[0];
					float invw = (w > 0.0f)? 1.0f/w: 0.0f;

					pixels[0] = f.x*invw;
					pixels[1] = f.y*invw;
					pixels[2] = f.z*invw;
					pixels[3] = f.w*invw;
				}
			}
			else {
				for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
					float4 f = make_float4(in[0], in[1], in[2], in[3]);

					pixels[0] = f.x*scale_exposure;
					pixels[1] = f.y*scale_exposure;
					pixels[2] = f.z*scale_exposure;

					/* clamp since alpha might be > 1.0 due to russian roulette */
					pixels[3] = saturate(f.w*scale);
				}
			}
		}

		return true;
	}

	return false;
}

/* Display Buffer */

DisplayBuffer::DisplayBuffer(Device *device_, bool linear)
{
	device = device_;
	draw_width = 0;
	draw_height = 0;
	transparent = true; /* todo: determine from background */
	half_float = linear;
}

DisplayBuffer::~DisplayBuffer()
{
	device_free();
}

void DisplayBuffer::device_free()
{
	if(rgba_byte.device_pointer) {
		device->pixels_free(rgba_byte);
		rgba_byte.clear();
	}
	if(rgba_half.device_pointer) {
		device->pixels_free(rgba_half);
		rgba_half.clear();
	}
}

void DisplayBuffer::reset(Device *device, BufferParams& params_)
{
	draw_width = 0;
	draw_height = 0;

	params = params_;

	/* free existing buffers */
	device_free();

	/* allocate display pixels */
	if(half_float) {
		rgba_half.resize(params.width, params.height);
		device->pixels_alloc(rgba_half);
	}
	else {
		rgba_byte.resize(params.width, params.height);
		device->pixels_alloc(rgba_byte);
	}
}

void DisplayBuffer::draw_set(int width, int height)
{
	assert(width <= params.width && height <= params.height);

	draw_width = width;
	draw_height = height;
}

void DisplayBuffer::draw(Device *device, const DeviceDrawParams& draw_params)
{
	if(draw_width != 0 && draw_height != 0) {
		device_memory& rgba = rgba_data();

		device->draw_pixels(rgba, 0, draw_width, draw_height, params.full_x, params.full_y, params.width, params.height, transparent, draw_params);
	}
}

bool DisplayBuffer::draw_ready()
{
	return (draw_width != 0 && draw_height != 0);
}

void DisplayBuffer::write(Device *device, const string& filename)
{
	int w = draw_width;
	int h = draw_height;

	if(w == 0 || h == 0)
		return;

	if(half_float)
		return;

	/* read buffer from device */
	device_memory& rgba = rgba_data();
	device->pixels_copy_from(rgba, 0, w, h);

	/* write image */
	ImageOutput *out = ImageOutput::create(filename);
	ImageSpec spec(w, h, 4, TypeDesc::UINT8);
	int scanlinesize = w*4*sizeof(uchar);

	out->open(filename, spec);

	/* conversion for different top/bottom convention */
	out->write_image(TypeDesc::UINT8,
		(uchar*)rgba.data_pointer + (h-1)*scanlinesize,
		AutoStride,
		-scanlinesize,
		AutoStride);

	out->close();

	delete out;
}

device_memory& DisplayBuffer::rgba_data()
{
	if(half_float)
		return rgba_half;
	else
		return rgba_byte;
}

CCL_NAMESPACE_END

<commit_msg>Cleanup, remove duplicated code<commit_after>/*
 * Copyright 2011-2013 Blender Foundation
 *
 * 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 <stdlib.h>

#include "buffers.h"
#include "device.h"

#include "util_debug.h"
#include "util_foreach.h"
#include "util_hash.h"
#include "util_image.h"
#include "util_math.h"
#include "util_opengl.h"
#include "util_time.h"
#include "util_types.h"

CCL_NAMESPACE_BEGIN

/* Buffer Params */

BufferParams::BufferParams()
{
	width = 0;
	height = 0;

	full_x = 0;
	full_y = 0;
	full_width = 0;
	full_height = 0;

	Pass::add(PASS_COMBINED, passes);
}

void BufferParams::get_offset_stride(int& offset, int& stride)
{
	offset = -(full_x + full_y*width);
	stride = width;
}

bool BufferParams::modified(const BufferParams& params)
{
	return !(full_x == params.full_x
		&& full_y == params.full_y
		&& width == params.width
		&& height == params.height
		&& full_width == params.full_width
		&& full_height == params.full_height
		&& Pass::equals(passes, params.passes));
}

int BufferParams::get_passes_size()
{
	int size = 0;

	for(size_t i = 0; i < passes.size(); i++)
		size += passes[i].components;

	return align_up(size, 4);
}

/* Render Buffer Task */

RenderTile::RenderTile()
{
	x = 0;
	y = 0;
	w = 0;
	h = 0;

	sample = 0;
	start_sample = 0;
	num_samples = 0;
	resolution = 0;

	offset = 0;
	stride = 0;

	buffer = 0;
	rng_state = 0;

	buffers = NULL;
}

/* Render Buffers */

RenderBuffers::RenderBuffers(Device *device_)
{
	device = device_;
}

RenderBuffers::~RenderBuffers()
{
	device_free();
}

void RenderBuffers::device_free()
{
	if(buffer.device_pointer) {
		device->mem_free(buffer);
		buffer.clear();
	}

	if(rng_state.device_pointer) {
		device->mem_free(rng_state);
		rng_state.clear();
	}
}

void RenderBuffers::reset(Device *device, BufferParams& params_)
{
	params = params_;

	/* free existing buffers */
	device_free();

	/* allocate buffer */
	buffer.resize(params.width*params.height*params.get_passes_size());
	device->mem_alloc(buffer, MEM_READ_WRITE);
	device->mem_zero(buffer);

	/* allocate rng state */
	rng_state.resize(params.width, params.height);

	device->mem_alloc(rng_state, MEM_READ_WRITE);
}

bool RenderBuffers::copy_from_device()
{
	if(!buffer.device_pointer)
		return false;

	device->mem_copy_from(buffer, 0, params.width, params.height, params.get_passes_size()*sizeof(float));

	return true;
}

bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels)
{
	int pass_offset = 0;

	for(size_t j = 0; j < params.passes.size(); j++) {
		Pass& pass = params.passes[j];

		if(pass.type != type) {
			pass_offset += pass.components;
			continue;
		}

		float *in = (float*)buffer.data_pointer + pass_offset;
		int pass_stride = params.get_passes_size();

		float scale = (pass.filter)? 1.0f/(float)sample: 1.0f;
		float scale_exposure = (pass.exposure)? scale*exposure: scale;

		int size = params.width*params.height;

		if(components == 1) {
			assert(pass.components == components);

			/* scalar */
			if(type == PASS_DEPTH) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
					float f = *in;
					pixels[0] = (f == 0.0f)? 1e10f: f*scale_exposure;
				}
			}
			else if(type == PASS_MIST) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
					float f = *in;
					pixels[0] = saturate(f*scale_exposure);
				}
			}
#ifdef WITH_CYCLES_DEBUG
			else if(type == PASS_BVH_TRAVERSAL_STEPS ||
			        type == PASS_RAY_BOUNCES)
			{
				for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
					float f = *in;
					pixels[0] = f*scale;
				}
			}
#endif
			else {
				for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
					float f = *in;
					pixels[0] = f*scale_exposure;
				}
			}
		}
		else if(components == 3) {
			assert(pass.components == 4);

			/* RGBA */
			if(type == PASS_SHADOW) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
					float4 f = make_float4(in[0], in[1], in[2], in[3]);
					float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;

					pixels[0] = f.x*invw;
					pixels[1] = f.y*invw;
					pixels[2] = f.z*invw;
				}
			}
			else if(pass.divide_type != PASS_NONE) {
				/* RGB lighting passes that need to divide out color */
				pass_offset = 0;
				for(size_t k = 0; k < params.passes.size(); k++) {
					Pass& color_pass = params.passes[k];
					if(color_pass.type == pass.divide_type)
						break;
					pass_offset += color_pass.components;
				}

				float *in_divide = (float*)buffer.data_pointer + pass_offset;

				for(int i = 0; i < size; i++, in += pass_stride, in_divide += pass_stride, pixels += 3) {
					float3 f = make_float3(in[0], in[1], in[2]);
					float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]);

					f = safe_divide_even_color(f*exposure, f_divide);

					pixels[0] = f.x;
					pixels[1] = f.y;
					pixels[2] = f.z;
				}
			}
			else {
				/* RGB/vector */
				for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
					float3 f = make_float3(in[0], in[1], in[2]);

					pixels[0] = f.x*scale_exposure;
					pixels[1] = f.y*scale_exposure;
					pixels[2] = f.z*scale_exposure;
				}
			}
		}
		else if(components == 4) {
			assert(pass.components == components);

			/* RGBA */
			if(type == PASS_SHADOW) {
				for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
					float4 f = make_float4(in[0], in[1], in[2], in[3]);
					float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;

					pixels[0] = f.x*invw;
					pixels[1] = f.y*invw;
					pixels[2] = f.z*invw;
					pixels[3] = 1.0f;
				}
			}
			else if(type == PASS_MOTION) {
				/* need to normalize by number of samples accumulated for motion */
				pass_offset = 0;
				for(size_t k = 0; k < params.passes.size(); k++) {
					Pass& color_pass = params.passes[k];
					if(color_pass.type == PASS_MOTION_WEIGHT)
						break;
					pass_offset += color_pass.components;
				}

				float *in_weight = (float*)buffer.data_pointer + pass_offset;

				for(int i = 0; i < size; i++, in += pass_stride, in_weight += pass_stride, pixels += 4) {
					float4 f = make_float4(in[0], in[1], in[2], in[3]);
					float w = in_weight[0];
					float invw = (w > 0.0f)? 1.0f/w: 0.0f;

					pixels[0] = f.x*invw;
					pixels[1] = f.y*invw;
					pixels[2] = f.z*invw;
					pixels[3] = f.w*invw;
				}
			}
			else {
				for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
					float4 f = make_float4(in[0], in[1], in[2], in[3]);

					pixels[0] = f.x*scale_exposure;
					pixels[1] = f.y*scale_exposure;
					pixels[2] = f.z*scale_exposure;

					/* clamp since alpha might be > 1.0 due to russian roulette */
					pixels[3] = saturate(f.w*scale);
				}
			}
		}

		return true;
	}

	return false;
}

/* Display Buffer */

DisplayBuffer::DisplayBuffer(Device *device_, bool linear)
{
	device = device_;
	draw_width = 0;
	draw_height = 0;
	transparent = true; /* todo: determine from background */
	half_float = linear;
}

DisplayBuffer::~DisplayBuffer()
{
	device_free();
}

void DisplayBuffer::device_free()
{
	if(rgba_byte.device_pointer) {
		device->pixels_free(rgba_byte);
		rgba_byte.clear();
	}
	if(rgba_half.device_pointer) {
		device->pixels_free(rgba_half);
		rgba_half.clear();
	}
}

void DisplayBuffer::reset(Device *device, BufferParams& params_)
{
	draw_width = 0;
	draw_height = 0;

	params = params_;

	/* free existing buffers */
	device_free();

	/* allocate display pixels */
	if(half_float) {
		rgba_half.resize(params.width, params.height);
		device->pixels_alloc(rgba_half);
	}
	else {
		rgba_byte.resize(params.width, params.height);
		device->pixels_alloc(rgba_byte);
	}
}

void DisplayBuffer::draw_set(int width, int height)
{
	assert(width <= params.width && height <= params.height);

	draw_width = width;
	draw_height = height;
}

void DisplayBuffer::draw(Device *device, const DeviceDrawParams& draw_params)
{
	if(draw_width != 0 && draw_height != 0) {
		device_memory& rgba = rgba_data();

		device->draw_pixels(rgba, 0, draw_width, draw_height, params.full_x, params.full_y, params.width, params.height, transparent, draw_params);
	}
}

bool DisplayBuffer::draw_ready()
{
	return (draw_width != 0 && draw_height != 0);
}

void DisplayBuffer::write(Device *device, const string& filename)
{
	int w = draw_width;
	int h = draw_height;

	if(w == 0 || h == 0)
		return;

	if(half_float)
		return;

	/* read buffer from device */
	device_memory& rgba = rgba_data();
	device->pixels_copy_from(rgba, 0, w, h);

	/* write image */
	ImageOutput *out = ImageOutput::create(filename);
	ImageSpec spec(w, h, 4, TypeDesc::UINT8);
	int scanlinesize = w*4*sizeof(uchar);

	out->open(filename, spec);

	/* conversion for different top/bottom convention */
	out->write_image(TypeDesc::UINT8,
		(uchar*)rgba.data_pointer + (h-1)*scanlinesize,
		AutoStride,
		-scanlinesize,
		AutoStride);

	out->close();

	delete out;
}

device_memory& DisplayBuffer::rgba_data()
{
	if(half_float)
		return rgba_half;
	else
		return rgba_byte;
}

CCL_NAMESPACE_END

<|endoftext|>


<commit_before>#pragma once
/**
 * Author(s):
 *  - Cedric GESTES <gestes@aldebaran-robotics.com>
 *
 * Copyright (C) 2011 Aldebaran Robotics
 */

/** @file
 *  @brief dll import/export and compiler message
 */

#ifndef _QI_API_HPP_
#define _QI_API_HPP_

// Deprecated
#if defined(__GNUC__) && defined(WITH_DEPRECATED) && !defined(QI_NO_API_DEPRECATED)
#  define QI_API_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER) && defined(WITH_DEPRECATED) && !defined(QI_NO_API_DEPRECATED)
#  define QI_API_DEPRECATED __declspec(deprecated)
#else
#  define QI_API_DEPRECATED
#endif

// For shared library
#if defined _WIN32 || defined __CYGWIN__
#  define QI_EXPORT_API __declspec(dllexport)
#  if defined _WINDLL
#    define QI_IMPORT_API __declspec(dllimport)
#  else
#    define QI_IMPORT_API
#  endif
#elif __GNUC__ >= 4
#  define QI_EXPORT_API __attribute__ ((visibility("default")))
#  define QI_IMPORT_API __attribute__ ((visibility("default")))
#else
#  define QI_EXPORT_API
#  define QI_IMPORT_API
#endif

// qi_EXPORTS controls which symbols are exported when libqi
// is compiled as a SHARED lib.
// DO NOT USE OUTSIDE LIBQI
#ifdef qi_EXPORTS
# define QI_API QI_EXPORT_API
#else
# define QI_API QI_IMPORT_API
#endif

// Macros adapted from opencv2.2
#if defined(_MSC_VER)
  #define QI_DO_PRAGMA(x) __pragma(x)
  #define __ALSTR2__(x) #x
  #define __ALSTR1__(x) __ALSTR2__(x)
  #define _ALMSVCLOC_ __FILE__ "("__ALSTR1__(__LINE__)") : "
  #define QI_MSG_PRAGMA(_msg) QI_DO_PRAGMA(message (_ALMSVCLOC_ _msg))
#elif defined(__GNUC__)
  #define QI_DO_PRAGMA(x) _Pragma (#x)
  #define QI_MSG_PRAGMA(_msg) QI_DO_PRAGMA(message (_msg))
#else
  #define QI_DO_PRAGMA(x)
  #define QI_MSG_PRAGMA(_msg)
#endif

// Use this macro to generate compiler warnings.
#if !defined(WITH_DEPRECATED) || defined(QI_NO_COMPILER_WARNING)
# define QI_COMPILER_WARNING(x)
#else
# define QI_COMPILER_WARNING(x) QI_MSG_PRAGMA("Warning: " #x)
#endif

/** \brief Deprecate a header, add a message to explain what user should do
 */
#if !defined(WITH_DEPRECATED) || defined(QI_NO_DEPRECATED_HEADER)
# define QI_DEPRECATED_HEADER(x)
#else
# define QI_DEPRECATED_HEADER(x) QI_MSG_PRAGMA("\
This file includes at least one deprecated or antiquated ALDEBARAN header \
which may be removed without further notice in the next version. \
Please consult the changelog for details. " #x)
#endif

/**
  \def QI_DEPRECATED_HEADER(x)
  \brief generate a compiler warning stating a header is deprecated.

  \def QI_COMPILER_WARNING(x)
  \brief generate a compiler warning

  \def QI_IMPORT_API
  \brief compiler flags to import a function or a class

  \def QI_EXPORT_API
  \brief compiler flags to export a function or a class
*/

#endif  // _QI_API_HPP_

<commit_msg>GLOBAL: remove link warnings LNK4049 and LNK4217<commit_after>#pragma once
/**
 * Author(s):
 *  - Cedric GESTES <gestes@aldebaran-robotics.com>
 *
 * Copyright (C) 2011 Aldebaran Robotics
 */

/** @file
 *  @brief dll import/export and compiler message
 */

#ifndef _QI_API_HPP_
#define _QI_API_HPP_

// Deprecated
#if defined(__GNUC__) && defined(WITH_DEPRECATED) && !defined(QI_NO_API_DEPRECATED)
#  define QI_API_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER) && defined(WITH_DEPRECATED) && !defined(QI_NO_API_DEPRECATED)
#  define QI_API_DEPRECATED __declspec(deprecated)
#else
#  define QI_API_DEPRECATED
#endif

// For shared library
#if defined _WIN32 || defined __CYGWIN__
#  define QI_EXPORT_API __declspec(dllexport)
#  if defined _WINDLL
#    define QI_IMPORT_API __declspec(dllimport)
#  else
#    define QI_IMPORT_API
#  endif
#elif __GNUC__ >= 4
#  define QI_EXPORT_API __attribute__ ((visibility("default")))
#  define QI_IMPORT_API __attribute__ ((visibility("default")))
#else
#  define QI_EXPORT_API
#  define QI_IMPORT_API
#endif

// qi_EXPORTS controls which symbols are exported when libqi
// is compiled as a SHARED lib.
// DO NOT USE OUTSIDE LIBQI
#ifdef qi_EXPORTS
# define QI_API QI_EXPORT_API
#elif defined(qi_IMPORTS)
# define QI_API QI_IMPORT_API
#else
# define QI_API
#endif

// Macros adapted from opencv2.2
#if defined(_MSC_VER)
  #define QI_DO_PRAGMA(x) __pragma(x)
  #define __ALSTR2__(x) #x
  #define __ALSTR1__(x) __ALSTR2__(x)
  #define _ALMSVCLOC_ __FILE__ "("__ALSTR1__(__LINE__)") : "
  #define QI_MSG_PRAGMA(_msg) QI_DO_PRAGMA(message (_ALMSVCLOC_ _msg))
#elif defined(__GNUC__)
  #define QI_DO_PRAGMA(x) _Pragma (#x)
  #define QI_MSG_PRAGMA(_msg) QI_DO_PRAGMA(message (_msg))
#else
  #define QI_DO_PRAGMA(x)
  #define QI_MSG_PRAGMA(_msg)
#endif

// Use this macro to generate compiler warnings.
#if !defined(WITH_DEPRECATED) || defined(QI_NO_COMPILER_WARNING)
# define QI_COMPILER_WARNING(x)
#else
# define QI_COMPILER_WARNING(x) QI_MSG_PRAGMA("Warning: " #x)
#endif

/** \brief Deprecate a header, add a message to explain what user should do
 */
#if !defined(WITH_DEPRECATED) || defined(QI_NO_DEPRECATED_HEADER)
# define QI_DEPRECATED_HEADER(x)
#else
# define QI_DEPRECATED_HEADER(x) QI_MSG_PRAGMA("\
This file includes at least one deprecated or antiquated ALDEBARAN header \
which may be removed without further notice in the next version. \
Please consult the changelog for details. " #x)
#endif

/**
  \def QI_DEPRECATED_HEADER(x)
  \brief generate a compiler warning stating a header is deprecated.

  \def QI_COMPILER_WARNING(x)
  \brief generate a compiler warning

  \def QI_IMPORT_API
  \brief compiler flags to import a function or a class

  \def QI_EXPORT_API
  \brief compiler flags to export a function or a class
*/

#endif  // _QI_API_HPP_

<|endoftext|>


<commit_before>#include "runner.hpp"
#include <iostream>
#include <typeinfo>
#include <memory>

namespace shiranui{
    namespace runtime{
        using shiranui::runtime::environment::Environment;
        using shiranui::runtime::value::Value;
        using shiranui::runtime::value::Integer;
        using shiranui::runtime::value::String;
        using shiranui::runtime::value::Boolean;
        using shiranui::runtime::value::Function;
        using shiranui::runtime::value::UserFunction;
        using shiranui::runtime::value::Return;
        using shiranui::runtime::value::SystemCall;
        using shiranui::runtime::value::BuiltinFunction;
        using shiranui::runtime::value::builtin::PrintFunction;
        ValEnv::ValEnv(){
            v = std::make_shared<Integer>(0);
            e = std::make_shared<Environment>();
        }
        ValEnv::ValEnv(Environment* e_){
            v = std::make_shared<Integer>(0);
            e = std::make_shared<Environment>(e_);
        }
        ValEnv::ValEnv(sp<Environment> e_){
            v = std::make_shared<Integer>(0);
            e = std::make_shared<Environment>(e_);
        }
        void ValEnv::set_value(sp<Value> v_){
            v = v_;
        }
        Runner::Runner() {}
        Runner::Runner(Runner* outer)
            : cur(outer->cur.e){
        }
        void Runner::visit(syntax::ast::Identifier& id){
            throw RuntimeException(); // never occur.
            return;
        }
        void Runner::visit(syntax::ast::Variable& var){
            if(var.value.name == "system_call"){
                cur.v = std::make_shared<SystemCall>();
                return;
            }
            if(cur.e->has(var.value)){
                cur.v = cur.e->get(var.value);
                return;
            }else{
                // is it really ok?
                throw NoSuchVariableException(std::make_shared<syntax::ast::Variable>(var));
            }
        }
        void Runner::visit(syntax::ast::Number& num){
            cur.v = std::make_shared<Integer>(num.value);
        }
        void Runner::visit(syntax::ast::String& s){
            cur.v = std::make_shared<String>(s.value);
        }
        void Runner::visit(syntax::ast::Block& block){
            Runner br(this);
            for(auto& st : block.statements){
                st->accept(br);
                cur.v = br.cur.v;
                sp<Return> r = std::dynamic_pointer_cast<Return>(cur.v);
                if(r != nullptr){
                    return;
                }
            }
        }
        void Runner::visit(syntax::ast::Function& f){
            cur.set_value(std::make_shared<UserFunction>(f.parameters,f.body));
        }
        void Runner::visit(syntax::ast::FunctionCall& fc){
            fc.function->accept(*this);
            sp<Value> func = cur.v;
            // check func.v is really function.
            {
                sp<UserFunction> f = std::dynamic_pointer_cast<UserFunction>(func);
                if(f != nullptr){
                    if(fc.arguments.size() != f->parameters.size()){
                        throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                    }
                    Runner inner(this);
                    for(int i=0;i<f->parameters.size();i++){
                        fc.arguments[i]->accept(*this);
                        // it is not const.
                        inner.cur.e->define(f->parameters[i],cur.v,false);
                    }
                    f->body->accept(inner);
                    sp<Return> ret = std::dynamic_pointer_cast<Return>(inner.cur.v);
                    if(ret == nullptr){
                        std::cerr << "WARN: this is not return value." << std::endl;
                    }else{
                        cur.v = ret->value;
                    }
                    return;
                }
            }
            {
                sp<SystemCall> f = std::dynamic_pointer_cast<SystemCall>(func);
                if(f != nullptr){
                    if(fc.arguments.size() != 1){
                        throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                    }
                    fc.arguments[0]->accept(*this);
                    sp<String> s = std::dynamic_pointer_cast<String>(cur.v);
                    if(s == nullptr){
                        throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                    }else{
                        if(s->value == "print"){
                            cur.v = std::make_shared<PrintFunction>();
                        }else{
                            throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                        }
                    }
                    return;
                }
            }
            {
                sp<BuiltinFunction> f = std::dynamic_pointer_cast<BuiltinFunction>(func);
                if(f != nullptr){
                    {
                        sp<PrintFunction> p = std::dynamic_pointer_cast<PrintFunction>(f);
                        if(p != nullptr){
                            if(fc.arguments.size() != 1){
                                throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                            }
                            fc.arguments[0]->accept(*this);
                            sp<String> s = std::dynamic_pointer_cast<String>(cur.v);
                            if(s == nullptr){
                                throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                            }else{
                                // replace this.
                                std::cout << s->value;
                                // cur.v =
                            }
                            return;
                        }
                    }
                }
            }
            throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
        }
        void Runner::visit(syntax::ast::BinaryOperator& bop){
            bop.left->accept(*this);
            sp<Value> left = cur.v;
            bop.right->accept(*this);
            sp<Value> right = cur.v;
            if(typeid(*left) != typeid(*right)){
                throw ConvertException(std::make_shared<syntax::ast::BinaryOperator>(bop));
            }
            {
                sp<Integer> l = std::dynamic_pointer_cast<Integer>(left);
                sp<Integer> r = std::dynamic_pointer_cast<Integer>(right);
                if(l != nullptr and r != nullptr){
                    if(bop.op == "="){
                        cur.v = std::make_shared<Boolean>(l->value == r->value);
                    }else if(bop.op == "/="){
                        cur.v = std::make_shared<Boolean>(l->value != r->value);
                    }else if(bop.op == "+"){
                        cur.v = std::make_shared<Integer>(l->value+r->value);
                    }else if(bop.op == "-"){
                        cur.v = std::make_shared<Integer>(l->value-r->value);
                    }else if(bop.op == "*"){
                        cur.v = std::make_shared<Integer>(l->value*r->value);
                    }else if(bop.op == "/"){
                        cur.v = std::make_shared<Integer>(l->value/r->value);
                    }else if(bop.op == "%"){
                        cur.v = std::make_shared<Integer>(l->value%r->value);
                    }else if(bop.op == "^"){
                    }else{
                        throw ConvertException(std::make_shared<syntax::ast::BinaryOperator>(bop));
                    }
                    return;
                }
            }
            {
                sp<Boolean> l = std::dynamic_pointer_cast<Boolean>(left);
                sp<Boolean> r = std::dynamic_pointer_cast<Boolean>(right);
                if(l != nullptr and r != nullptr){
                    if(bop.op == "="){
                        cur.v = std::make_shared<Boolean>(l->value == r->value);
                    }else if(bop.op == "/="){
                        cur.v = std::make_shared<Boolean>(l->value != r->value);
                    }else if(bop.op == "and"){
                        cur.v = std::make_shared<Boolean>(l->value and r->value);
                    }else if(bop.op == "or"){
                        cur.v = std::make_shared<Boolean>(l->value or r->value);
                    }else{
                        throw ConvertException(std::make_shared<syntax::ast::BinaryOperator>(bop));
                    }
                    return;
                }
            }
            throw ConvertException(std::make_shared<syntax::ast::BinaryOperator>(bop));
            if(bop.op == "="){
            }else if(bop.op == "/="){
            }else if(bop.op == "+"){
            }else if(bop.op == "-"){
            }else if(bop.op == "*"){
            }else if(bop.op == "/"){
            }else if(bop.op == "%"){
            }else if(bop.op == "^"){
            }else if(bop.op == "and"){
            }else if(bop.op == "or"){
            }

        }
        void Runner::visit(syntax::ast::UnaryOperator& uop){
                  if(uop.op == "not"){
            }else if(uop.op == "+"){
            }else if(uop.op == "-"){
            }
            return;
        }
        void Runner::visit(syntax::ast::IfElseExpression&){
            return;
        }
        void Runner::visit(syntax::ast::Definement& def){
            def.value->accept(*this);
            cur.e->define(def.id,cur.v,def.is_const);
            return;
        }
        void Runner::visit(syntax::ast::ReturnStatement& ret){
            ret.value->accept(*this);
            cur.v = std::make_shared<Return>(cur.v);
            return;
        }
        void Runner::visit(syntax::ast::IfElseStatement& ies){
            ies.pred->accept(*this);
            sp<Boolean> bp = std::dynamic_pointer_cast<Boolean>(cur.v);
            if(bp == nullptr){
                throw ConvertException(ies.pred);
            }
            if(bp->value){
                ies.ifblock->accept(*this);
            }else{
                ies.elseblock->accept(*this);
            }
            return;
        }
        // do not eval firsttime.
        void Runner::visit(syntax::ast::FlyLine& line){
            return;
        }
        void Runner::visit(syntax::ast::SourceCode& sc){
            for(auto s : sc.statements){
                s->accept(*this);
            }
            return;
        }

    }
}
<commit_msg>Add integer version of print.<commit_after>#include "runner.hpp"
#include <iostream>
#include <typeinfo>
#include <memory>

namespace shiranui{
    namespace runtime{
        using shiranui::runtime::environment::Environment;
        using shiranui::runtime::value::Value;
        using shiranui::runtime::value::Integer;
        using shiranui::runtime::value::String;
        using shiranui::runtime::value::Boolean;
        using shiranui::runtime::value::Function;
        using shiranui::runtime::value::UserFunction;
        using shiranui::runtime::value::Return;
        using shiranui::runtime::value::SystemCall;
        using shiranui::runtime::value::BuiltinFunction;
        using shiranui::runtime::value::builtin::PrintFunction;
        ValEnv::ValEnv(){
            v = std::make_shared<Integer>(0);
            e = std::make_shared<Environment>();
        }
        ValEnv::ValEnv(Environment* e_){
            v = std::make_shared<Integer>(0);
            e = std::make_shared<Environment>(e_);
        }
        ValEnv::ValEnv(sp<Environment> e_){
            v = std::make_shared<Integer>(0);
            e = std::make_shared<Environment>(e_);
        }
        void ValEnv::set_value(sp<Value> v_){
            v = v_;
        }
        Runner::Runner() {}
        Runner::Runner(Runner* outer)
            : cur(outer->cur.e){
        }
        void Runner::visit(syntax::ast::Identifier& id){
            throw RuntimeException(); // never occur.
            return;
        }
        void Runner::visit(syntax::ast::Variable& var){
            if(var.value.name == "system_call"){
                cur.v = std::make_shared<SystemCall>();
                return;
            }
            if(cur.e->has(var.value)){
                cur.v = cur.e->get(var.value);
                return;
            }else{
                // is it really ok?
                throw NoSuchVariableException(std::make_shared<syntax::ast::Variable>(var));
            }
        }
        void Runner::visit(syntax::ast::Number& num){
            cur.v = std::make_shared<Integer>(num.value);
        }
        void Runner::visit(syntax::ast::String& s){
            cur.v = std::make_shared<String>(s.value);
        }
        void Runner::visit(syntax::ast::Block& block){
            Runner br(this);
            for(auto& st : block.statements){
                st->accept(br);
                cur.v = br.cur.v;
                sp<Return> r = std::dynamic_pointer_cast<Return>(cur.v);
                if(r != nullptr){
                    return;
                }
            }
        }
        void Runner::visit(syntax::ast::Function& f){
            cur.set_value(std::make_shared<UserFunction>(f.parameters,f.body));
        }
        void Runner::visit(syntax::ast::FunctionCall& fc){
            fc.function->accept(*this);
            sp<Value> func = cur.v;
            // check func.v is really function.
            {
                sp<UserFunction> f = std::dynamic_pointer_cast<UserFunction>(func);
                if(f != nullptr){
                    if(fc.arguments.size() != f->parameters.size()){
                        throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                    }
                    Runner inner(this);
                    for(int i=0;i<f->parameters.size();i++){
                        fc.arguments[i]->accept(*this);
                        // it is not const.
                        inner.cur.e->define(f->parameters[i],cur.v,false);
                    }
                    f->body->accept(inner);
                    sp<Return> ret = std::dynamic_pointer_cast<Return>(inner.cur.v);
                    if(ret == nullptr){
                        std::cerr << "WARN: this is not return value." << std::endl;
                    }else{
                        cur.v = ret->value;
                    }
                    return;
                }
            }
            {
                sp<SystemCall> f = std::dynamic_pointer_cast<SystemCall>(func);
                if(f != nullptr){
                    if(fc.arguments.size() != 1){
                        throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                    }
                    fc.arguments[0]->accept(*this);
                    sp<String> s = std::dynamic_pointer_cast<String>(cur.v);
                    if(s == nullptr){
                        throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                    }else{
                        if(s->value == "print"){
                            cur.v = std::make_shared<PrintFunction>();
                        }else{
                            throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                        }
                    }
                    return;
                }
            }
            {
                sp<BuiltinFunction> f = std::dynamic_pointer_cast<BuiltinFunction>(func);
                if(f != nullptr){
                    {
                        sp<PrintFunction> p = std::dynamic_pointer_cast<PrintFunction>(f);
                        if(p != nullptr){
                            if(fc.arguments.size() != 1){
                                throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                            }
                            fc.arguments[0]->accept(*this);
                            {
                                sp<String> s = std::dynamic_pointer_cast<String>(cur.v);
                                if(s != nullptr){
                                    std::cout << s->value << std::endl;
                                    return;
                                }
                            }
                            {
                                sp<Integer> s = std::dynamic_pointer_cast<Integer>(cur.v);
                                if(s != nullptr){
                                    std::cout << s->value << std::endl;
                                    return;
                                }
                            }
                            throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
                            return;
                        }
                    }
                }
            }
            throw ConvertException(std::make_shared<syntax::ast::FunctionCall>(fc));
        }
        void Runner::visit(syntax::ast::BinaryOperator& bop){
            bop.left->accept(*this);
            sp<Value> left = cur.v;
            bop.right->accept(*this);
            sp<Value> right = cur.v;
            if(typeid(*left) != typeid(*right)){
                throw ConvertException(std::make_shared<syntax::ast::BinaryOperator>(bop));
            }
            {
                sp<Integer> l = std::dynamic_pointer_cast<Integer>(left);
                sp<Integer> r = std::dynamic_pointer_cast<Integer>(right);
                if(l != nullptr and r != nullptr){
                    if(bop.op == "="){
                        cur.v = std::make_shared<Boolean>(l->value == r->value);
                    }else if(bop.op == "/="){
                        cur.v = std::make_shared<Boolean>(l->value != r->value);
                    }else if(bop.op == "+"){
                        cur.v = std::make_shared<Integer>(l->value+r->value);
                    }else if(bop.op == "-"){
                        cur.v = std::make_shared<Integer>(l->value-r->value);
                    }else if(bop.op == "*"){
                        cur.v = std::make_shared<Integer>(l->value*r->value);
                    }else if(bop.op == "/"){
                        cur.v = std::make_shared<Integer>(l->value/r->value);
                    }else if(bop.op == "%"){
                        cur.v = std::make_shared<Integer>(l->value%r->value);
                    }else if(bop.op == "^"){
                    }else{
                        throw ConvertException(std::make_shared<syntax::ast::BinaryOperator>(bop));
                    }
                    return;
                }
            }
            {
                sp<Boolean> l = std::dynamic_pointer_cast<Boolean>(left);
                sp<Boolean> r = std::dynamic_pointer_cast<Boolean>(right);
                if(l != nullptr and r != nullptr){
                    if(bop.op == "="){
                        cur.v = std::make_shared<Boolean>(l->value == r->value);
                    }else if(bop.op == "/="){
                        cur.v = std::make_shared<Boolean>(l->value != r->value);
                    }else if(bop.op == "and"){
                        cur.v = std::make_shared<Boolean>(l->value and r->value);
                    }else if(bop.op == "or"){
                        cur.v = std::make_shared<Boolean>(l->value or r->value);
                    }else{
                        throw ConvertException(std::make_shared<syntax::ast::BinaryOperator>(bop));
                    }
                    return;
                }
            }
            throw ConvertException(std::make_shared<syntax::ast::BinaryOperator>(bop));
            if(bop.op == "="){
            }else if(bop.op == "/="){
            }else if(bop.op == "+"){
            }else if(bop.op == "-"){
            }else if(bop.op == "*"){
            }else if(bop.op == "/"){
            }else if(bop.op == "%"){
            }else if(bop.op == "^"){
            }else if(bop.op == "and"){
            }else if(bop.op == "or"){
            }

        }
        void Runner::visit(syntax::ast::UnaryOperator& uop){
                  if(uop.op == "not"){
            }else if(uop.op == "+"){
            }else if(uop.op == "-"){
            }
            return;
        }
        void Runner::visit(syntax::ast::IfElseExpression&){
            return;
        }
        void Runner::visit(syntax::ast::Definement& def){
            def.value->accept(*this);
            cur.e->define(def.id,cur.v,def.is_const);
            return;
        }
        void Runner::visit(syntax::ast::ReturnStatement& ret){
            ret.value->accept(*this);
            cur.v = std::make_shared<Return>(cur.v);
            return;
        }
        void Runner::visit(syntax::ast::IfElseStatement& ies){
            ies.pred->accept(*this);
            sp<Boolean> bp = std::dynamic_pointer_cast<Boolean>(cur.v);
            if(bp == nullptr){
                throw ConvertException(ies.pred);
            }
            if(bp->value){
                ies.ifblock->accept(*this);
            }else{
                ies.elseblock->accept(*this);
            }
            return;
        }
        // do not eval firsttime.
        void Runner::visit(syntax::ast::FlyLine& line){
            return;
        }
        void Runner::visit(syntax::ast::SourceCode& sc){
            for(auto s : sc.statements){
                s->accept(*this);
            }
            return;
        }

    }
}
<|endoftext|>


<commit_before>//
// Copyright RIME Developers
// Distributed under the BSD License
//
// 2011-09-11 GONG Chen <chen.sst@gmail.com>
//
#include <rime/common.h>
#include <rime/composition.h>
#include <rime/context.h>
#include <rime/engine.h>
#include <rime/key_event.h>
#include <rime/key_table.h>
#include <rime/menu.h>
#include <rime/schema.h>
#include <rime/gear/selector.h>

namespace rime {

Selector::Selector(const Ticket& ticket) : Processor(ticket) {
}

ProcessResult Selector::ProcessKeyEvent(const KeyEvent& key_event) {
  if (key_event.release() || key_event.alt())
    return kNoop;
  Context* ctx = engine_->context();
  if (ctx->composition().empty())
    return kNoop;
  Segment& current_segment(ctx->composition().back());
  if (!current_segment.menu || current_segment.HasTag("raw"))
    return kNoop;
  int ch = key_event.keycode();
  if (ch == XK_Prior || ch == XK_KP_Prior) {
    PageUp(ctx);
    return kAccepted;
  }
  if (ch == XK_Next || ch == XK_KP_Next) {
    PageDown(ctx);
    return kAccepted;
  }
  if (ch == XK_Up || ch == XK_KP_Up) {
    if (ctx->get_option("_horizontal")) {
      PageUp(ctx);
    } else {
      CursorUp(ctx);
    }
    return kAccepted;
  }
  if (ch == XK_Down || ch == XK_KP_Down) {
    if (ctx->get_option("_horizontal")) {
      PageDown(ctx);
    } else {
      CursorDown(ctx);
    }
    return kAccepted;
  }
  if (ch == XK_Left || ch == XK_KP_Left) {
    if (!key_event.ctrl() &&
        !key_event.shift() &&
        ctx->caret_pos() == ctx->input().length() &&
        ctx->get_option("_horizontal") &&
        CursorUp(ctx)) {
      return kAccepted;
    }
    return kNoop;
  }
  if (ch == XK_Right || ch == XK_KP_Right) {
    if (!key_event.ctrl() &&
        !key_event.shift() &&
        ctx->caret_pos() == ctx->input().length() &&
        ctx->get_option("_horizontal") &&
        CursorDown(ctx)) {
      return kAccepted;
    }
    return kNoop;
  }
  if (ch == XK_Home || ch == XK_KP_Home) {
    return Home(ctx) ? kAccepted : kNoop;
  }
  if (ch == XK_End || ch == XK_KP_End) {
    return End(ctx) ? kAccepted : kNoop;
  }
  int index = -1;
  const string& select_keys(engine_->schema()->select_keys());
  if (!select_keys.empty() &&
      !key_event.ctrl() &&
      ch >= 0x20 && ch < 0x7f) {
    size_t pos = select_keys.find((char)ch);
    if (pos != string::npos) {
      index = static_cast<int>(pos);
    }
  }
  else if (ch >= XK_0 && ch <= XK_9)
    index = ((ch - XK_0) + 9) % 10;
  else if (ch >= XK_KP_0 && ch <= XK_KP_9)
    index = ((ch - XK_KP_0) + 9) % 10;
  if (index >= 0) {
    SelectCandidateAt(ctx, index);
    return kAccepted;
  }
  // not handled
  return kNoop;
}

bool Selector::PageUp(Context* ctx) {
  Composition& comp = ctx->composition();
  if (comp.empty())
    return false;
  int page_size = engine_->schema()->page_size();
  int selected_index = comp.back().selected_index;
  int index = selected_index < page_size ? 0 : selected_index - page_size;
  comp.back().selected_index = index;
  comp.back().tags.insert("paging");
  return true;
}

bool Selector::PageDown(Context* ctx) {
  Composition& comp = ctx->composition();
  if (comp.empty() || !comp.back().menu)
    return false;
  int page_size = engine_->schema()->page_size();
  int index = comp.back().selected_index + page_size;
  int page_start = (index / page_size) * page_size;
  int candidate_count = comp.back().menu->Prepare(page_start + page_size);
  if (candidate_count <= page_start)
    return false;
  if (index >= candidate_count)
    index = candidate_count - 1;
  comp.back().selected_index = index;
  comp.back().tags.insert("paging");
  return true;

}

bool Selector::CursorUp(Context* ctx) {
  Composition& comp = ctx->composition();
  if (comp.empty())
    return false;
  int index = comp.back().selected_index;
  if (index <= 0)
    return false;
  comp.back().selected_index = index - 1;
  comp.back().tags.insert("paging");
  return true;
}

bool Selector::CursorDown(Context* ctx) {
  Composition& comp = ctx->composition();
  if (comp.empty() || !comp.back().menu)
    return false;
  int index = comp.back().selected_index + 1;
  int candidate_count = comp.back().menu->Prepare(index + 1);
  if (candidate_count <= index)
    return false;
  comp.back().selected_index = index;
  comp.back().tags.insert("paging");
  return true;
}

bool Selector::Home(Context* ctx) {
  if (ctx->composition().empty())
    return false;
  Segment& seg(ctx->composition().back());
  if (seg.selected_index > 0) {
    seg.selected_index = 0;
    return true;
  }
  return false;
}

bool Selector::End(Context* ctx) {
  if (ctx->caret_pos() < ctx->input().length()) {
    // navigator should handle this
    return false;
  }
  // this is cool:
  return Home(ctx);
}

bool Selector::SelectCandidateAt(Context* ctx, int index) {
  Composition& comp = ctx->composition();
  if (comp.empty())
    return false;
  int page_size = engine_->schema()->page_size();
  if (index >= page_size)
    return false;
  int selected_index = comp.back().selected_index;
  int page_start = (selected_index / page_size) * page_size;
  return ctx->Select(page_start + index);
}

}  // namespace rime
<commit_msg>(fix) in horizontal mode, right arrow key should not fall back to moving caret when reached the end of candidate list.<commit_after>//
// Copyright RIME Developers
// Distributed under the BSD License
//
// 2011-09-11 GONG Chen <chen.sst@gmail.com>
//
#include <rime/common.h>
#include <rime/composition.h>
#include <rime/context.h>
#include <rime/engine.h>
#include <rime/key_event.h>
#include <rime/key_table.h>
#include <rime/menu.h>
#include <rime/schema.h>
#include <rime/gear/selector.h>

namespace rime {

Selector::Selector(const Ticket& ticket) : Processor(ticket) {
}

ProcessResult Selector::ProcessKeyEvent(const KeyEvent& key_event) {
  if (key_event.release() || key_event.alt())
    return kNoop;
  Context* ctx = engine_->context();
  if (ctx->composition().empty())
    return kNoop;
  Segment& current_segment(ctx->composition().back());
  if (!current_segment.menu || current_segment.HasTag("raw"))
    return kNoop;
  int ch = key_event.keycode();
  if (ch == XK_Prior || ch == XK_KP_Prior) {
    PageUp(ctx);
    return kAccepted;
  }
  if (ch == XK_Next || ch == XK_KP_Next) {
    PageDown(ctx);
    return kAccepted;
  }
  if (ch == XK_Up || ch == XK_KP_Up) {
    if (ctx->get_option("_horizontal")) {
      PageUp(ctx);
    } else {
      CursorUp(ctx);
    }
    return kAccepted;
  }
  if (ch == XK_Down || ch == XK_KP_Down) {
    if (ctx->get_option("_horizontal")) {
      PageDown(ctx);
    } else {
      CursorDown(ctx);
    }
    return kAccepted;
  }
  if (ch == XK_Left || ch == XK_KP_Left) {
    if (!key_event.ctrl() &&
        !key_event.shift() &&
        ctx->caret_pos() == ctx->input().length() &&
        ctx->get_option("_horizontal") &&
        CursorUp(ctx)) {
      return kAccepted;
    }
    return kNoop;
  }
  if (ch == XK_Right || ch == XK_KP_Right) {
    if (!key_event.ctrl() &&
        !key_event.shift() &&
        ctx->caret_pos() == ctx->input().length() &&
        ctx->get_option("_horizontal")) {
      CursorDown(ctx);
      return kAccepted;
    }
    return kNoop;
  }
  if (ch == XK_Home || ch == XK_KP_Home) {
    return Home(ctx) ? kAccepted : kNoop;
  }
  if (ch == XK_End || ch == XK_KP_End) {
    return End(ctx) ? kAccepted : kNoop;
  }
  int index = -1;
  const string& select_keys(engine_->schema()->select_keys());
  if (!select_keys.empty() &&
      !key_event.ctrl() &&
      ch >= 0x20 && ch < 0x7f) {
    size_t pos = select_keys.find((char)ch);
    if (pos != string::npos) {
      index = static_cast<int>(pos);
    }
  }
  else if (ch >= XK_0 && ch <= XK_9)
    index = ((ch - XK_0) + 9) % 10;
  else if (ch >= XK_KP_0 && ch <= XK_KP_9)
    index = ((ch - XK_KP_0) + 9) % 10;
  if (index >= 0) {
    SelectCandidateAt(ctx, index);
    return kAccepted;
  }
  // not handled
  return kNoop;
}

bool Selector::PageUp(Context* ctx) {
  Composition& comp = ctx->composition();
  if (comp.empty())
    return false;
  int page_size = engine_->schema()->page_size();
  int selected_index = comp.back().selected_index;
  int index = selected_index < page_size ? 0 : selected_index - page_size;
  comp.back().selected_index = index;
  comp.back().tags.insert("paging");
  return true;
}

bool Selector::PageDown(Context* ctx) {
  Composition& comp = ctx->composition();
  if (comp.empty() || !comp.back().menu)
    return false;
  int page_size = engine_->schema()->page_size();
  int index = comp.back().selected_index + page_size;
  int page_start = (index / page_size) * page_size;
  int candidate_count = comp.back().menu->Prepare(page_start + page_size);
  if (candidate_count <= page_start)
    return false;
  if (index >= candidate_count)
    index = candidate_count - 1;
  comp.back().selected_index = index;
  comp.back().tags.insert("paging");
  return true;

}

bool Selector::CursorUp(Context* ctx) {
  Composition& comp = ctx->composition();
  if (comp.empty())
    return false;
  int index = comp.back().selected_index;
  if (index <= 0)
    return false;
  comp.back().selected_index = index - 1;
  comp.back().tags.insert("paging");
  return true;
}

bool Selector::CursorDown(Context* ctx) {
  Composition& comp = ctx->composition();
  if (comp.empty() || !comp.back().menu)
    return false;
  int index = comp.back().selected_index + 1;
  int candidate_count = comp.back().menu->Prepare(index + 1);
  if (candidate_count <= index)
    return false;
  comp.back().selected_index = index;
  comp.back().tags.insert("paging");
  return true;
}

bool Selector::Home(Context* ctx) {
  if (ctx->composition().empty())
    return false;
  Segment& seg(ctx->composition().back());
  if (seg.selected_index > 0) {
    seg.selected_index = 0;
    return true;
  }
  return false;
}

bool Selector::End(Context* ctx) {
  if (ctx->caret_pos() < ctx->input().length()) {
    // navigator should handle this
    return false;
  }
  // this is cool:
  return Home(ctx);
}

bool Selector::SelectCandidateAt(Context* ctx, int index) {
  Composition& comp = ctx->composition();
  if (comp.empty())
    return false;
  int page_size = engine_->schema()->page_size();
  if (index >= page_size)
    return false;
  int selected_index = comp.back().selected_index;
  int page_start = (selected_index / page_size) * page_size;
  return ctx->Select(page_start + index);
}

}  // namespace rime
<|endoftext|>


<commit_before>/* This file is part of Ingen.
 * Copyright 2007-2011 David Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen 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 General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <gtkmm.h>
#include "ingen/ServerInterface.hpp"
#include "ingen/shared/LV2URIMap.hpp"
#include "ingen/client/NodeModel.hpp"
#include "ingen/client/PluginModel.hpp"
#include "App.hpp"
#include "NodeMenu.hpp"
#include "WindowFactory.hpp"
#include "WidgetFactory.hpp"

using namespace std;
using namespace Ingen::Client;

namespace Ingen {
namespace GUI {

NodeMenu::NodeMenu(BaseObjectType*                   cobject,
                   const Glib::RefPtr<Gtk::Builder>& xml)
	: ObjectMenu(cobject, xml)
	, _controls_menuitem(NULL)
	, _presets_menu(NULL)
{
	xml->get_widget("node_controls_menuitem", _controls_menuitem);
	xml->get_widget("node_popup_gui_menuitem", _popup_gui_menuitem);
	xml->get_widget("node_embed_gui_menuitem", _embed_gui_menuitem);
	xml->get_widget("node_randomize_menuitem", _randomize_menuitem);
}

void
NodeMenu::init(App& app, SharedPtr<const NodeModel> node)
{
	ObjectMenu::init(app, node);

	_learn_menuitem->signal_activate().connect(sigc::mem_fun(this,
			&NodeMenu::on_menu_learn));
	_controls_menuitem->signal_activate().connect(
		sigc::bind(sigc::mem_fun(_app->window_factory(),
		                         &WindowFactory::present_controls),
		           node));
	_popup_gui_menuitem->signal_activate().connect(
		sigc::mem_fun(signal_popup_gui, &sigc::signal<void>::emit));
	_embed_gui_menuitem->signal_toggled().connect(
		sigc::mem_fun(this, &NodeMenu::on_menu_embed_gui));
	_randomize_menuitem->signal_activate().connect(
		sigc::mem_fun(this, &NodeMenu::on_menu_randomize));

	const PluginModel* plugin = dynamic_cast<const PluginModel*>(node->plugin());
	if (plugin && plugin->type() == PluginModel::LV2 && plugin->has_ui()) {
		_popup_gui_menuitem->show();
		_embed_gui_menuitem->show();
	} else {
		_popup_gui_menuitem->hide();
		_embed_gui_menuitem->hide();
	}

	if (plugin && plugin->type() == PluginModel::LV2) {
		LilvNode* preset_pred = lilv_new_uri(
			plugin->lilv_world(),
			"http://lv2plug.in/ns/dev/presets#hasPreset");
		LilvNode* title_pred = lilv_new_uri(
			plugin->lilv_world(),
			"http://dublincore.org/documents/dcmi-namespace/title");
		LilvNodes* presets = lilv_plugin_get_value(
			plugin->lilv_plugin(), preset_pred);
		if (presets) {
			_presets_menu = Gtk::manage(new Gtk::Menu());

			LILV_FOREACH(nodes, i, presets) {
				const LilvNode* uri = lilv_nodes_get(presets, i);
				LilvNodes* titles   = lilv_world_find_nodes(
					plugin->lilv_world(), uri, title_pred, NULL);
				if (titles) {
					const LilvNode* title = lilv_nodes_get_first(titles);
					_presets_menu->items().push_back(
						Gtk::Menu_Helpers::MenuElem(
							lilv_node_as_string(title),
							sigc::bind(
								sigc::mem_fun(this, &NodeMenu::on_preset_activated),
								string(lilv_node_as_string(uri)))));

					// I have no idea why this is necessary, signal_activated doesn't work
					// in this menu (and only this menu)
					Gtk::MenuItem* item = &(_presets_menu->items().back());
					item->signal_button_release_event().connect(
						sigc::bind<0>(sigc::mem_fun(this, &NodeMenu::on_preset_clicked),
						              string(lilv_node_as_string(uri))));
				}
			}
			items().push_front(Gtk::Menu_Helpers::ImageMenuElem("_Presets",
					*(manage(new Gtk::Image(Gtk::Stock::INDEX, Gtk::ICON_SIZE_MENU)))));
			Gtk::MenuItem* presets_menu_item = &(items().front());
			presets_menu_item->set_submenu(*_presets_menu);
		}
		lilv_nodes_free(presets);
		lilv_node_free(title_pred);
		lilv_node_free(preset_pred);
	}

	if (has_control_inputs())
		_randomize_menuitem->show();
	else
		_randomize_menuitem->hide();

	if (plugin && (plugin->uri().str() == "http://drobilla.net/ns/ingen-internals#Controller"
			|| plugin->uri().str() == "http://drobilla.net/ns/ingen-internals#Trigger"))
		_learn_menuitem->show();
	else
		_learn_menuitem->hide();

	_enable_signal = true;
}

void
NodeMenu::on_menu_embed_gui()
{
	signal_embed_gui.emit(_embed_gui_menuitem->get_active());
}

void
NodeMenu::on_menu_randomize()
{
	_app->engine()->bundle_begin();

	const NodeModel* const nm = (NodeModel*)_object.get();
	for (NodeModel::Ports::const_iterator i = nm->ports().begin(); i != nm->ports().end(); ++i) {
		if ((*i)->is_input() && _app->can_control(i->get())) {
			float min = 0.0f, max = 1.0f;
			nm->port_value_range(*i, min, max, _app->sample_rate());
			const float val = ((rand() / (float)RAND_MAX) * (max - min) + min);
			_app->engine()->set_property((*i)->path(),
					_app->uris().ingen_value, val);
		}
	}

	_app->engine()->bundle_end();
}

void
NodeMenu::on_menu_disconnect()
{
	_app->engine()->disconnect_all(_object->parent()->path(), _object->path());
}

void
NodeMenu::on_preset_activated(const std::string& uri)
{
	const NodeModel* const   node   = (NodeModel*)_object.get();
	const PluginModel* const plugin = dynamic_cast<const PluginModel*>(node->plugin());

	LilvNode* port_pred = lilv_new_uri(
		plugin->lilv_world(),
		"http://lv2plug.in/ns/lv2core#port");
	LilvNode* symbol_pred = lilv_new_uri(
		plugin->lilv_world(),
		"http://lv2plug.in/ns/lv2core#symbol");
	LilvNode* value_pred = lilv_new_uri(
		plugin->lilv_world(),
		"http://lv2plug.in/ns/ext/presets#value");
	LilvNode*  subject = lilv_new_uri(plugin->lilv_world(), uri.c_str());
	LilvNodes* ports   = lilv_world_find_nodes(
		plugin->lilv_world(),
		subject,
		port_pred,
		NULL);
	_app->engine()->bundle_begin();
	LILV_FOREACH(nodes, i, ports) {
		const LilvNode* uri = lilv_nodes_get(ports, i);
		LilvNodes* values = lilv_world_find_nodes(
			plugin->lilv_world(), uri, value_pred, NULL);
		LilvNodes* symbols = lilv_world_find_nodes(
			plugin->lilv_world(), uri, symbol_pred, NULL);
		if (values && symbols) {
			const LilvNode* val = lilv_nodes_get_first(values);
			const LilvNode* sym = lilv_nodes_get_first(symbols);
			_app->engine()->set_property(
				node->path().base() + lilv_node_as_string(sym),
				_app->uris().ingen_value,
				lilv_node_as_float(val));
		}
	}
	_app->engine()->bundle_end();
	lilv_nodes_free(ports);
	lilv_node_free(value_pred);
	lilv_node_free(symbol_pred);
	lilv_node_free(port_pred);
}

bool
NodeMenu::on_preset_clicked(const std::string& uri, GdkEventButton* ev)
{
	on_preset_activated(uri);
	return false;
}

bool
NodeMenu::has_control_inputs()
{
	const NodeModel* const nm = (NodeModel*)_object.get();
	for (NodeModel::Ports::const_iterator i = nm->ports().begin(); i != nm->ports().end(); ++i)
		if ((*i)->is_input() && (*i)->is_numeric())
			return true;

	return false;
}

void
NodeMenu::enable_controls_menuitem()
{
	_controls_menuitem->property_sensitive() = true;
}

void
NodeMenu::disable_controls_menuitem()
{
	_controls_menuitem->property_sensitive() = false;
}

} // namespace GUI
} // namespace Ingen
<commit_msg>Use rdfs:label for preset labels (fix ticket #668). Use correct namespace for dc.<commit_after>/* This file is part of Ingen.
 * Copyright 2007-2011 David Robillard <http://drobilla.net>
 *
 * Ingen is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * Ingen 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 General Public License for details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <gtkmm.h>
#include "ingen/ServerInterface.hpp"
#include "ingen/shared/LV2URIMap.hpp"
#include "ingen/client/NodeModel.hpp"
#include "ingen/client/PluginModel.hpp"
#include "App.hpp"
#include "NodeMenu.hpp"
#include "WindowFactory.hpp"
#include "WidgetFactory.hpp"

using namespace std;
using namespace Ingen::Client;

namespace Ingen {
namespace GUI {

NodeMenu::NodeMenu(BaseObjectType*                   cobject,
                   const Glib::RefPtr<Gtk::Builder>& xml)
	: ObjectMenu(cobject, xml)
	, _controls_menuitem(NULL)
	, _presets_menu(NULL)
{
	xml->get_widget("node_controls_menuitem", _controls_menuitem);
	xml->get_widget("node_popup_gui_menuitem", _popup_gui_menuitem);
	xml->get_widget("node_embed_gui_menuitem", _embed_gui_menuitem);
	xml->get_widget("node_randomize_menuitem", _randomize_menuitem);
}

void
NodeMenu::init(App& app, SharedPtr<const NodeModel> node)
{
	ObjectMenu::init(app, node);

	_learn_menuitem->signal_activate().connect(sigc::mem_fun(this,
			&NodeMenu::on_menu_learn));
	_controls_menuitem->signal_activate().connect(
		sigc::bind(sigc::mem_fun(_app->window_factory(),
		                         &WindowFactory::present_controls),
		           node));
	_popup_gui_menuitem->signal_activate().connect(
		sigc::mem_fun(signal_popup_gui, &sigc::signal<void>::emit));
	_embed_gui_menuitem->signal_toggled().connect(
		sigc::mem_fun(this, &NodeMenu::on_menu_embed_gui));
	_randomize_menuitem->signal_activate().connect(
		sigc::mem_fun(this, &NodeMenu::on_menu_randomize));

	const PluginModel* plugin = dynamic_cast<const PluginModel*>(node->plugin());
	if (plugin && plugin->type() == PluginModel::LV2 && plugin->has_ui()) {
		_popup_gui_menuitem->show();
		_embed_gui_menuitem->show();
	} else {
		_popup_gui_menuitem->hide();
		_embed_gui_menuitem->hide();
	}

	if (plugin && plugin->type() == PluginModel::LV2) {
		LilvNode* preset_pred = lilv_new_uri(
			plugin->lilv_world(),
			"http://lv2plug.in/ns/ext/presets#hasPreset");
		LilvNode* title_pred = lilv_new_uri(
			plugin->lilv_world(),
			"http://www.w3.org/2000/01/rdf-schema#label");
		LilvNodes* presets = lilv_plugin_get_value(
			plugin->lilv_plugin(), preset_pred);
		if (presets) {
			_presets_menu = Gtk::manage(new Gtk::Menu());

			LILV_FOREACH(nodes, i, presets) {
				const LilvNode* uri = lilv_nodes_get(presets, i);
				LilvNodes* titles   = lilv_world_find_nodes(
					plugin->lilv_world(), uri, title_pred, NULL);
				if (titles) {
					const LilvNode* title = lilv_nodes_get_first(titles);
					_presets_menu->items().push_back(
						Gtk::Menu_Helpers::MenuElem(
							lilv_node_as_string(title),
							sigc::bind(
								sigc::mem_fun(this, &NodeMenu::on_preset_activated),
								string(lilv_node_as_string(uri)))));

					// I have no idea why this is necessary, signal_activated doesn't work
					// in this menu (and only this menu)
					Gtk::MenuItem* item = &(_presets_menu->items().back());
					item->signal_button_release_event().connect(
						sigc::bind<0>(sigc::mem_fun(this, &NodeMenu::on_preset_clicked),
						              string(lilv_node_as_string(uri))));
				}
			}
			items().push_front(Gtk::Menu_Helpers::ImageMenuElem("_Presets",
					*(manage(new Gtk::Image(Gtk::Stock::INDEX, Gtk::ICON_SIZE_MENU)))));
			Gtk::MenuItem* presets_menu_item = &(items().front());
			presets_menu_item->set_submenu(*_presets_menu);
		}
		lilv_nodes_free(presets);
		lilv_node_free(title_pred);
		lilv_node_free(preset_pred);
	}

	if (has_control_inputs())
		_randomize_menuitem->show();
	else
		_randomize_menuitem->hide();

	if (plugin && (plugin->uri().str() == "http://drobilla.net/ns/ingen-internals#Controller"
			|| plugin->uri().str() == "http://drobilla.net/ns/ingen-internals#Trigger"))
		_learn_menuitem->show();
	else
		_learn_menuitem->hide();

	_enable_signal = true;
}

void
NodeMenu::on_menu_embed_gui()
{
	signal_embed_gui.emit(_embed_gui_menuitem->get_active());
}

void
NodeMenu::on_menu_randomize()
{
	_app->engine()->bundle_begin();

	const NodeModel* const nm = (NodeModel*)_object.get();
	for (NodeModel::Ports::const_iterator i = nm->ports().begin(); i != nm->ports().end(); ++i) {
		if ((*i)->is_input() && _app->can_control(i->get())) {
			float min = 0.0f, max = 1.0f;
			nm->port_value_range(*i, min, max, _app->sample_rate());
			const float val = ((rand() / (float)RAND_MAX) * (max - min) + min);
			_app->engine()->set_property((*i)->path(),
					_app->uris().ingen_value, val);
		}
	}

	_app->engine()->bundle_end();
}

void
NodeMenu::on_menu_disconnect()
{
	_app->engine()->disconnect_all(_object->parent()->path(), _object->path());
}

void
NodeMenu::on_preset_activated(const std::string& uri)
{
	const NodeModel* const   node   = (NodeModel*)_object.get();
	const PluginModel* const plugin = dynamic_cast<const PluginModel*>(node->plugin());

	LilvNode* port_pred = lilv_new_uri(
		plugin->lilv_world(),
		"http://lv2plug.in/ns/lv2core#port");
	LilvNode* symbol_pred = lilv_new_uri(
		plugin->lilv_world(),
		"http://lv2plug.in/ns/lv2core#symbol");
	LilvNode* value_pred = lilv_new_uri(
		plugin->lilv_world(),
		"http://lv2plug.in/ns/ext/presets#value");
	LilvNode*  subject = lilv_new_uri(plugin->lilv_world(), uri.c_str());
	LilvNodes* ports   = lilv_world_find_nodes(
		plugin->lilv_world(),
		subject,
		port_pred,
		NULL);
	_app->engine()->bundle_begin();
	LILV_FOREACH(nodes, i, ports) {
		const LilvNode* uri = lilv_nodes_get(ports, i);
		LilvNodes* values = lilv_world_find_nodes(
			plugin->lilv_world(), uri, value_pred, NULL);
		LilvNodes* symbols = lilv_world_find_nodes(
			plugin->lilv_world(), uri, symbol_pred, NULL);
		if (values && symbols) {
			const LilvNode* val = lilv_nodes_get_first(values);
			const LilvNode* sym = lilv_nodes_get_first(symbols);
			_app->engine()->set_property(
				node->path().base() + lilv_node_as_string(sym),
				_app->uris().ingen_value,
				lilv_node_as_float(val));
		}
	}
	_app->engine()->bundle_end();
	lilv_nodes_free(ports);
	lilv_node_free(value_pred);
	lilv_node_free(symbol_pred);
	lilv_node_free(port_pred);
}

bool
NodeMenu::on_preset_clicked(const std::string& uri, GdkEventButton* ev)
{
	on_preset_activated(uri);
	return false;
}

bool
NodeMenu::has_control_inputs()
{
	const NodeModel* const nm = (NodeModel*)_object.get();
	for (NodeModel::Ports::const_iterator i = nm->ports().begin(); i != nm->ports().end(); ++i)
		if ((*i)->is_input() && (*i)->is_numeric())
			return true;

	return false;
}

void
NodeMenu::enable_controls_menuitem()
{
	_controls_menuitem->property_sensitive() = true;
}

void
NodeMenu::disable_controls_menuitem()
{
	_controls_menuitem->property_sensitive() = false;
}

} // namespace GUI
} // namespace Ingen
<|endoftext|>


<commit_before>#include <tuple>

#include "crib_hand_helper/hand_counter.h"

using std::make_tuple;
using std::get;

namespace
{
  using SetsOfTwo = std::vector<std::tuple<int, int>>;
  using SetsOfThree = std::vector<std::tuple<int, int, int>>;
  using SetsOfFour = std::vector<std::tuple<int, int, int, int>>;
  using SetsOfFive = std::vector<std::tuple<int, int, int, int, int>>;

  const SetsOfTwo SETS_OF_TWO = {
      make_tuple(0, 1), make_tuple(0, 2), make_tuple(0, 3), make_tuple(0, 4),
      make_tuple(1, 2), make_tuple(1, 3), make_tuple(1, 4), make_tuple(2, 3),
      make_tuple(2, 4), make_tuple(3, 4)};

  const SetsOfThree SETS_OF_THREE = {make_tuple(0, 1, 2), make_tuple(0, 1, 3),
                                     make_tuple(0, 1, 4), make_tuple(0, 2, 3),
                                     make_tuple(0, 2, 4), make_tuple(0, 3, 4),
                                     make_tuple(1, 2, 3), make_tuple(1, 2, 4),
                                     make_tuple(1, 3, 4), make_tuple(2, 3, 4)};

  const SetsOfFour SETS_OF_FOUR = {
      make_tuple(0, 1, 2, 3), make_tuple(0, 1, 2, 4), make_tuple(0, 1, 3, 4),
      make_tuple(0, 2, 3, 4), make_tuple(1, 2, 3, 4)};

  const SetsOfFive SETS_OF_FIVE = {make_tuple(0, 1, 2, 3, 4)};

  unsigned count_fifteens(const Hand& hand, const Card& cut)
  {
    Hand h = hand;
    h.push_back(cut);

    unsigned score = 0;

    for (const auto& indices : SETS_OF_TWO)
    {
      if (h[get<0>(indices)].value + h[get<1>(indices)].value == 15)
      {
        score += 2;
      }
    }

    for (const auto& indices : SETS_OF_THREE)
    {
      if (h[get<0>(indices)].value + h[get<1>(indices)].value +
              h[get<2>(indices)].value ==
          15)
      {
        score += 2;
      }
    }

    for (const auto& indices : SETS_OF_FOUR)
    {
      if (h[get<0>(indices)].value + h[get<1>(indices)].value +
              h[get<2>(indices)].value + h[get<3>(indices)].value ==
          15)
      {
        score += 2;
      }
    }

    for (const auto& indices : SETS_OF_FIVE)
    {
      if (h[get<0>(indices)].value + h[get<1>(indices)].value +
              h[get<2>(indices)].value + h[get<3>(indices)].value +
              h[get<4>(indices)].value ==
          15)
      {
        score += 2;
      }
    }

    return score;
  }

  unsigned count_pairs(const Hand& hand, const Card& cut)
  {
    Hand h = hand;
    h.push_back(cut);

    unsigned score = 0;
    for (const auto& indices : SETS_OF_TWO)
    {
      if (h[std::get<0>(indices)].rank == h[std::get<1>(indices)].rank)
      {
        score += 2;
      }
    }

    return score;
  }

  unsigned count_runs(const Hand& hand, const Card& cut)
  {
    return 0;
  }

  unsigned count_flush(const Hand& hand, const Card& cut)
  {
    const auto& suit = hand[0].suit;
    for (Hand::size_type i = 1; i < hand.size(); ++i)
    {
      if (hand[i].suit != suit)
      {
        return 0;
      }
    }
    return cut.suit == suit ? 5 : 4;
  }

  unsigned count_nobs(const Hand& hand, const Card& cut)
  {
    for (const auto& card : hand)
    {
      if (card.name == 'J' && card.suit == cut.suit)
      {
        return 1;
      }
    }
    return 0;
  }
}

unsigned count_hand(const Hand& hand, const Card& cut)
{
  return count_fifteens(hand, cut) + count_pairs(hand, cut) +
         count_runs(hand, cut) + count_flush(hand, cut) + count_nobs(hand, cut);
}
<commit_msg>Finished hand counter (untested).<commit_after>#include <algorithm>
#include <vector>

#include "crib_hand_helper/hand_counter.h"

namespace
{
  using IndexSets = std::vector<std::vector<Hand::size_type>>;
  using AllSets = std::vector<IndexSets>;

  const IndexSets SETS_OF_TWO = {{0, 1}, {0, 2}, {0, 3}, {0, 4}, {1, 2},
                                 {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}};

  const IndexSets SETS_OF_THREE = {{0, 1, 2}, {0, 1, 3}, {0, 1, 4}, {0, 2, 3},
                                   {0, 2, 4}, {0, 3, 4}, {1, 2, 3}, {1, 2, 4},
                                   {1, 3, 4}, {2, 3, 4}};

  const IndexSets SETS_OF_FOUR = {
      {0, 1, 2, 3}, {0, 1, 2, 4}, {0, 1, 3, 4}, {0, 2, 3, 4}, {1, 2, 3, 4}};

  const IndexSets SETS_OF_FIVE = {{0, 1, 2, 3, 4}};

  const AllSets ALL_SETS = {SETS_OF_TWO, SETS_OF_THREE, SETS_OF_FOUR, SETS_OF_FIVE};

  unsigned count_fifteens(const Hand& hand, const Card& cut)
  {
    Hand h = hand;
    h.push_back(cut);

    unsigned score = 0;
    unsigned sum = 0;

    for (const auto& sets : ALL_SETS)
    {
      for (const auto& indices : sets)
      {
        sum = 0;
        for (const auto& index : indices)
        {
          sum += h[index].value;
        }
        if (sum == 15)
        {
          score += 2;
        }
      }
    }

    return score;
  }

  unsigned count_pairs(const Hand& hand, const Card& cut)
  {
    Hand h = hand;
    h.push_back(cut);

    unsigned score = 0;
    for (const auto& indices : SETS_OF_TWO)
    {
      if (h[indices[0]].rank == h[indices[1]].rank)
      {
        score += 2;
      }
    }

    return score;
  }

  unsigned count_runs_of_three(const Hand& hand)
  {
    unsigned score = 0;

    for (const auto& indices : SETS_OF_THREE)
    {
      for (Hand::size_type i = 1; i < indices.size(); ++i)
      {
        if (hand[indices[i]].rank != hand[indices[i-1]].rank + 1)
        {
          break;
        }
        else if (i == indices.size() - 1)
        {
          score += 3;
        }
      }
    }

    return score;
  }

  unsigned count_runs_of_four(const Hand& hand)
  {
    unsigned score = 0;

    for (const auto& indices : SETS_OF_FOUR)
    {
      for (Hand::size_type i = 1; i < indices.size(); ++i)
      {
        if (hand[indices[i]].rank != hand[indices[i-1]].rank + 1)
        {
          break;
        }
        else if (i == indices.size() - 1)
        {
          score += 4;
        }
      }
    }

    return score;
  }

  unsigned count_runs_of_five(const Hand& hand)
  {
    for (Hand::size_type i = 1; i < hand.size(); ++i)
    {
      if (hand[i].rank != hand[i-1].rank + 1)
      {
        return 0;
      }
    }
    return 5;
  }

  unsigned count_runs(const Hand& hand, const Card& cut)
  {
    Hand h = hand;
    h.push_back(cut);
    std::sort(h.begin(), h.end(), [](const Card& card_1, const Card& card_2) {
      return card_1.rank > card_2.rank;
    });

    auto score = count_runs_of_five(h);

    if (score == 0)
    {
      score += count_runs_of_four(h);
      if (score == 0)
      {
        score += count_runs_of_three(h);
      }
    }

    return score;
  }

  unsigned count_flush(const Hand& hand, const Card& cut)
  {
    const auto& suit = hand[0].suit;
    for (Hand::size_type i = 1; i < hand.size(); ++i)
    {
      if (hand[i].suit != suit)
      {
        return 0;
      }
    }
    return cut.suit == suit ? 5 : 4;
  }

  unsigned count_nobs(const Hand& hand, const Card& cut)
  {
    for (const auto& card : hand)
    {
      if (card.name == 'J' && card.suit == cut.suit)
      {
        return 1;
      }
    }
    return 0;
  }
}

unsigned count_hand(const Hand& hand, const Card& cut)
{
  return count_fifteens(hand, cut) + count_pairs(hand, cut) +
         count_runs(hand, cut) + count_flush(hand, cut) + count_nobs(hand, cut);
}
<|endoftext|>