view dstep/internal/Traits.d @ 17:c2fba45df857

Fixed: indexOf didn't compile
author Jacob Carlborg <doob@me.com>
date Sun, 10 Jan 2010 13:22:58 +0100
parents 19885b43130e
children
line wrap: on
line source

/**
 * Copyright: Copyright (c) 2009 Jacob Carlborg.
 * Authors: Jacob Carlborg
 * Version: Initial created: Apr 28, 2009
 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
 */
module dstep.internal.Traits;

import dstep.objc.bridge.Bridge;
import dstep.internal.String;

/**
 * Returns the name of the given function
 * 
 * Params:
 *     func = the function alias to get the name of
 *     
 * Returns: the name of the function 
 */
template functionNameOf (alias func)
{
	version(LDC)
		const functionNameOf = (&func).stringof[1 .. $];
	
	else
		const functionNameOf = (&func).stringof[2 .. $];
}

/**
 * Returns the parameter names of the given function
 * 
 * Params:
 *     func = the function alias to get the parameter names of
 *     
 * Returns: an array of strings containing the parameter names 
 */
template parameterNamesOf (alias func)
{
	const parameterNamesOf = parameterNamesOfImpl!(func);
}

private string[] parameterNamesOfImpl (alias func) ()
{
	string funcStr = typeof(&func).stringof;

	auto start = funcStr.indexOf('(');
	auto end = funcStr.indexOf(')');
	
	const firstPattern = ' ';
	const secondPattern = ',';
	
	funcStr = funcStr[start + 1 .. end];
	
	if (funcStr == "")
		return null;
		
	funcStr ~= secondPattern;
	
	string token;
	string[] arr;
	
	foreach (c ; funcStr)
	{		
		if (c != firstPattern && c != secondPattern)
			token ~= c;
		
		else
		{			
			if (token)
				arr ~= token;
			
			token = null;
		}			
	}
	
	if (arr.length == 1)
		return arr;
	
	string[] result;
	bool skip = false;
	
	foreach (str ; arr)
	{
		skip = !skip;
		
		if (skip)
			continue;
		
		result ~= str;
	}
	
	return result;
}

/**
 * Compile-time function to get the index of the give element.
 * 
 * Performs a linear scan, returning the index of the first occurrence 
 * of the specified element in the array, or U.max if the array does 
 * not contain the element.
 * 
 * Params:
 *     arr = the array to get the index of the element from
 *     element = the element to find
 *     
 * Returns: the index of the element or size_t.max if the element was not found.
 */
private size_t indexOf (T) (T[] arr, T element)
{
	foreach (i, e ; arr)
		if (e == element)
			return i;
	
	return size_t.max;
}

//FIXME fix this when http://d.puremagic.com/issues/show_bug.cgi?id=3512 is fixed
version (none)
{

/**
 * Compile-time function to get the index of the give element.
 * 
 * Performs a linear scan, returning the index of the first occurrence 
 * of the specified element in the array, or U.max if the array does 
 * not contain the element.
 * 
 * Params:
 *     arr = the array to get the index of the element from
 *     element = the element to find
 *     
 * Returns: the index of the element or size_t.max if the element was not found.
 */
private size_t indexOf (T) (T[] arr, dchar element)
{
	static assert(is(T == char) || is(T == wchar) || is(T == dchar), `dstep.internal.Traits.indexOf: The given type "` ~ T.stringof ~ `" is not valid, it has to be char, wchar or dchar`);
	
	foreach (i, dchar e ; arr)
		if (e == element)
			return i;
	
	return size_t.max;
}
}

/**
 * Evaluates to true if $(D_PARAM T) has a instance method with the given name
 * 
 * Params:
 * 		T = the type of the class/struct
 * 		method = the name of the method
 */
template hasInstanceMethod (T, string method)
{
	const hasInstanceMethod = is(typeof({
		T t;
		mixin("auto f = &t." ~ method ~ ";");
	}));
}

/**
 * Evaluates to true if $(D_PARAM T) has a class method with the given name
 * 
 * Params:
 * 		T = the type of the class/struct
 * 		method = the name of the method
 */
template hasClassMethod (T, string method)
{
	const hasClassMethod = is(typeof({
		mixin("auto f = &T." ~ method ~ ";");
	}));
}

/**
 * Evaluates to true if $(D_PARAM T) has a either a class method or a instance method
 * with the given name.
 * 
 * Params:
 * 		T = the type of the class/struct
 * 		method = the name of the method
 */
template hasMethod (T, string method)
{
	const hasMethod = hasClassMethod!(T, method) || hasInstanceMethod!(T, method);
}

/**
 * Evaluates to true if $(D_PARAM T) has a field with the given name
 * 
 * Params:
 * 		T = the type of the class/struct
 * 		field = the name of the field
 */
template hasField (T, string field)
{
	const hasField = is(typeof({
		T t;
		mixin("auto f = t." ~ field ~ ";");
	}));
}

/// Evaluates to true if $(D_PARAM T) has binded methods
template hasBindedMethods (T)
{
	const bool hasBindedMethods = hasField!(T, Bridge.objcClassMethodDeclarationVar) || hasField!(T, Bridge.objcMethodDeclarationVar);
}