using System;
using System.Collections.Generic;
using System.Text;
using FastReport.Data;
using FastReport.Engine;
using FastReport.Utils;
namespace FastReport.Code
{
///
/// This class is used to pass find arguments to some methods of the CodeUtils class.
///
public class FindTextArgs
{
private int startIndex;
private int endIndex;
private string openBracket;
private string closeBracket;
private FastString text;
private string foundText;
///
/// The start position of the search. After the search, this property points to
/// the begin of an expression.
///
public int StartIndex
{
get { return startIndex; }
set { startIndex = value; }
}
///
/// After the search, this property points to the end of an expression.
///
public int EndIndex
{
get { return endIndex; }
set { endIndex = value; }
}
///
/// The char sequence used to find the expression's begin.
///
public string OpenBracket
{
get { return openBracket; }
set { openBracket = value; }
}
///
/// The char sequence used to find the expression's end.
///
public string CloseBracket
{
get { return closeBracket; }
set { closeBracket = value; }
}
///
/// The text with embedded expressions.
///
public FastString Text
{
get { return text; }
set { text = value; }
}
///
/// The last found expression.
///
public string FoundText
{
get { return foundText; }
set { foundText = value; }
}
}
///
/// This static class contains methods that may be used to find expressions embedded
/// in the object's text.
///
public static class CodeUtils
{
internal enum Language
{
Cs,
Vb
}
private static bool isTypeSuffixesInitialized = false;
private static Dictionary typeSuffixes;
#region Private Methods
private static bool TypeHasSuffix(Type type)
{
return typeSuffixes.ContainsKey(type);
}
private static string GetTypeSuffix(Type type, Language lang)
{
string[] suffix;
typeSuffixes.TryGetValue(type, out suffix);
return suffix[(int)lang];
}
private static void InitializeTypeSuffixes()
{
typeSuffixes = new Dictionary();
//c# and vb type prefixes
typeSuffixes.Add(typeof(float), new string[] { "F", "F" });
typeSuffixes.Add(typeof(double), new string[] { "D", "R" });
typeSuffixes.Add(typeof(uint), new string[] { "U", "" });
typeSuffixes.Add(typeof(long), new string[] { "L", "L" });
typeSuffixes.Add(typeof(ulong), new string[] { "UL", "UL" });
typeSuffixes.Add(typeof(decimal), new string[] { "M", "D" });
isTypeSuffixesInitialized = true;
}
// adjusts StartIndex to the next char after end of string. Returns true if string is correct.
private static bool SkipString(FindTextArgs args)
{
if (args.Text[args.StartIndex] == '"')
args.StartIndex++;
else
return true;
while (args.StartIndex < args.Text.Length)
{
if (args.Text[args.StartIndex] == '"')
{
if (args.Text[args.StartIndex - 1] != '\\')
{
args.StartIndex++;
return true;
}
}
args.StartIndex++;
}
return false;
}
// find matching open and close brackets starting from StartIndex. Takes strings into account.
// Returns true if matching brackets found. Also returns FoundText with text inside brackets,
// StartIndex pointing to the OpenBracket and EndIndex pointing to the next char after CloseBracket.
private static bool FindMatchingBrackets(FindTextArgs args, bool skipLeadingStrings)
{
if (!skipLeadingStrings)
{
args.StartIndex = args.Text.IndexOf(args.OpenBracket, args.StartIndex);
if (args.StartIndex == -1)
return false;
}
int saveStartIndex = 0;
int brCount = 0;
while (args.StartIndex < args.Text.Length)
{
if (!SkipString(args))
return false;
if (args.StartIndex + args.OpenBracket.Length > args.Text.Length)
return false;
if (args.Text.SubstringCompare(args.StartIndex, args.OpenBracket))
{
if (brCount == 0)
saveStartIndex = args.StartIndex;
brCount++;
}
else if (args.Text.SubstringCompare(args.StartIndex, args.CloseBracket))
{
brCount--;
if (brCount == 0)
{
args.EndIndex = args.StartIndex + args.CloseBracket.Length;
args.StartIndex = saveStartIndex;
args.FoundText = args.Text.Substring(args.StartIndex + args.OpenBracket.Length,
args.EndIndex - args.StartIndex - args.OpenBracket.Length - args.CloseBracket.Length);
return true;
}
}
args.StartIndex++;
}
return false;
}
#endregion
#region Internal Methods
// determines whether given index is inside brackets, or is after OpenBracket
internal static bool IndexInsideBrackets(FindTextArgs args)
{
int pos = args.StartIndex;
args.StartIndex = 0;
while (args.StartIndex < pos)
{
// find open bracket
args.StartIndex = args.Text.IndexOf(args.OpenBracket, args.StartIndex);
if (args.StartIndex == -1)
return false;
// missing close bracket
if (!FindMatchingBrackets(args, false))
return true;
// pos is inside brackets
if (args.StartIndex < pos && args.EndIndex > pos)
return true;
args.StartIndex = args.EndIndex;
}
return false;
}
internal static string GetOptionalParameter(System.Reflection.ParameterInfo par, Language lang)
{
if(!isTypeSuffixesInitialized)
InitializeTypeSuffixes();
string optionalParamString = " = ";
if (par.DefaultValue.GetType().IsEnum)
optionalParamString += par.DefaultValue.GetType().Name + ".";
optionalParamString += par.DefaultValue.ToString();
if (TypeHasSuffix(par.ParameterType))
optionalParamString += GetTypeSuffix(par.ParameterType, lang);
return optionalParamString;
}
internal static string FixExpressionWithBrackets(string expression)
{
string result = expression;
if (expression.StartsWith("[") && expression.EndsWith("]"))
{
string tempExpression = expression.Substring(1, expression.Length - 2);
int firstOpen = tempExpression.IndexOf("[");
int firstClose = tempExpression.IndexOf("]");
int lastOpen = tempExpression.LastIndexOf("[");
int lastClose = tempExpression.LastIndexOf("]");
if ((firstOpen < 0 && firstClose >= 0) || (lastOpen >= 0 && lastClose < 0)
|| (firstOpen >= 0 && firstClose >= 0 && firstClose < firstOpen)
|| (lastOpen >= 0 && lastClose >= 0 && lastOpen > lastClose))
{
result = expression;
}
else
{
result = tempExpression;
}
}
else
{
result = expression;
}
return result;
}
#endregion
///
/// Returns expressions found in the text.
///
/// Text that may contain expressions.
/// The char sequence used to find the start of expression.
/// The char sequence used to find the end of expression.
/// Array of expressions if found; otherwise return an empty array.
public static string[] GetExpressions(string text, string openBracket, string closeBracket)
{
List expressions = new List();
FindTextArgs args = new FindTextArgs();
args.Text = new FastString(text);
args.OpenBracket = openBracket;
args.CloseBracket = closeBracket;
while (args.StartIndex < args.Text.Length) //text.Length
{
if (!FindMatchingBrackets(args, false))
break;
expressions.Add(args.FoundText);
args.StartIndex = args.EndIndex;
}
return expressions.ToArray();
}
///
/// Gets first expression found in the text.
///
/// Object with find arguments.
/// Indicates whether to skip strings.
/// The expression if found; otherwise, returns null.
public static string GetExpression(FindTextArgs args, bool skipStrings)
{
if (args.StartIndex < args.Text.Length)
{
if (FindMatchingBrackets(args, skipStrings))
return args.FoundText;
}
return null;
}
}
}