text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Inference.Parser;

using ISExpression = Inference.Interpreter.LISP.ISExpression;
using IConvertibleToGraph = Inference.Interpreter.SASL.IConvertibleToGraph;

namespace Inference.Interpreter
{
    #region Interfaces

    public interface IGlobalInfoOps
    {
        void Clear();
        string LoadPreset(string presetName);
        void LoadPresets();
        bool SetScoping(bool dynamicScoping);
        bool SetDebug(bool debug);
    }

    public interface IGlobalInfo<T>
    {
        ITokenizer Tokenizer { get; }
        IParser Parser { get; }
        T FalseValue { get; }
        T TrueValue { get; }
        bool ValueIsFalse(T value);
        EnvironmentFrame<T> GlobalEnvironment { get; }
        Dictionary<Name, FunctionDefinition<T>> FunctionDefinitions { get; }
        Dictionary<Name, IMacroDefinition<T>> MacroDefinitions { get; }
        bool ValueIsInteger(T value);
        int ValueAsInteger(T value);
        T IntegerAsValue(int value);
        Random RandomNumberGenerator { get; }
        bool DynamicScoping { get; set; }
        bool Debug { get; set; }
    }

    public interface IExpression<T>
    {
        T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo);
    }

    public interface IMacroDefinition<T>
    {
        int ArgumentCount { get; }
        T InvokeMacro(List<IExpression<T>> unevaluatedArguments, EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo);
    }

    #endregion

    #region EvaluationException

    public class EvaluationException : ExceptionWithLineAndColumnNumbers
    {
        public EvaluationException(string message, int line, int column)
            //: base("Evaluation error: " + message, line, column)
            : base(message, line, column)
        {
        }
    }

    #endregion

    #region Name

    public class Name
    {
        public readonly string Value;
        public readonly int Line;
        public readonly int Column;

        public Name(string value, int line, int column)
        {

            if (string.IsNullOrEmpty(value))
            {
                throw new ArgumentNullException("value", "A Name cannot have a null or empty value");
            }

            Value = value;
            Line = line;
            Column = column;
        }

        public override string ToString()
        {
            return Value;
        }

        public override bool Equals(object obj)
        {

            if (object.ReferenceEquals(this, obj))
            {
                return true;
            }

            Name otherName = obj as Name;

            return otherName != null && Value == otherName.Value;
        }

        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }
    }

    #endregion

    #region EnvironmentFrame<T>

    public class EnvironmentFrame<T>
    {
        public readonly Dictionary<Variable<T>, T> Dict;
        public readonly EnvironmentFrame<T> Next;

        public EnvironmentFrame(EnvironmentFrame<T> next)
        {
            Dict = new Dictionary<Variable<T>, T>();
            Next = next;
        }

        public bool IsDefined(Variable<T> key)
        {

            if (Dict.ContainsKey(key))
            {
                return true;
            }

            if (Next != null)
            {
                return Next.IsDefined(key);
            }

            return false;
        }

        public T Lookup(Variable<T> key)
        {

            if (Dict.ContainsKey(key))
            {
#if DEAD_CODE
                Console.WriteLine("Lookup: The value of {0} in {1} environment frame is {2}",
                    key, (Next != null) ? "a local" : "the global", Dict[key]);
#endif
                return Dict[key];
            }

            if (Next != null)
            {
                return Next.Lookup(key);
            }

            throw new KeyNotFoundException(string.Format("Environment.Lookup() : No value found for variable '{0}'.", key.Name));
        }

        public void Add(Variable<T> key, T value)
        {
            Dict[key] = value;
        }

        public void AddBubbleDown(Variable<T> key, T value)
        {

            if (!Dict.ContainsKey(key) && Next != null)
            {
                Next.AddBubbleDown(key, value);     // Bubble down towards the global environment.
            }
            else
            {
                // Bug fix: Before 2013/12/04, the "else" above was absent, and the code below was executed unconditionally.
#if DEAD_CODE
                Console.WriteLine("AddBubbleDown: The new value of {0} in {1} environment frame is {2}",
                    key, (Next != null) ? "a local" : "the global", value);
#endif
                Add(key, value);
            }
        }

        public void Compose(List<Variable<T>> keys, List<T> values)
        {

            if (keys.Count != values.Count)
            {
                throw new ArgumentException("Environment.Compose() : The keys list and the values list have different lengths.");
            }

            for (var i = 0; i < keys.Count; ++i)
            {
                Add(keys[i], values[i]);
            }
        }
    }

    #endregion

    #region Variable<T>

    public class Variable<T> : IExpression<T>, IConvertibleToGraph
    {
        public readonly string Name;
        public readonly int Line;
        public readonly int Column;

        public Variable(string name, int line, int column)
        {

            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException("name", "A Variable cannot have a null or empty name");
            }

            /*
            //Console.WriteLine("Creating a Variable named '{0}'.", name);

            if (name.StartsWith("Inference"))
            {
                throw new Exception(string.Format("Error: Creating variable named '{0}'.", name));
            }
             */

            Name = name;
            Line = line;
            Column = column;
        }

        public override string ToString()
        {
            return Name;
        }

        public override bool Equals(object obj)
        {

            if (object.ReferenceEquals(this, obj))
            {
                return true;
            }

            Variable<T> otherVariable = obj as Variable<T>;

            return otherVariable != null && Name == otherVariable.Name;
        }

        public override int GetHashCode()
        {
            return Name.GetHashCode();
        }

        public T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {

            try
            {
                return localEnvironment.Lookup(this);
            }
            catch (KeyNotFoundException)
            {
                throw new EvaluationException(
                    string.Format("Variable<T>.Evaluate() : No value found for variable '{0}'", Name),
                    Line, Column);
            }
        }

        public IExpression<ISExpression> ConvertToGraph()
        {

            if (this is IExpression<ISExpression>)
            {
                return (IExpression<ISExpression>)this;
            }

            throw new NotImplementedException("Variable<T>.ConvertToGraph() : T is not ISExpression.");
        }
    }

    #endregion

    #region VariableList<T>

    public class VariableList<T>
    {
        public readonly List<Variable<T>> Value;

        public VariableList()
        {
            Value = new List<Variable<T>>();
        }

        public override string ToString()
        {
            return "(" + string.Join(" ", Value) + ")";
        }
    }

    #endregion

    #region FunctionDefinition<T>

    public class FunctionDefinition<T> : IExpression<T>
    {
        public readonly Name FunctionName;
        public readonly VariableList<T> ArgList;
        public readonly IExpression<T> Body;

        public FunctionDefinition(Name functionName, VariableList<T> argList, IExpression<T> body)
        {
            FunctionName = functionName;
            ArgList = argList;
            Body = body;
        }

        public override string ToString()
        {
            return string.Format("(define {0} {1} {2})", FunctionName, ArgList, Body);
        }

        public T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
            globalInfo.FunctionDefinitions[FunctionName] = this;
            return globalInfo.TrueValue;
        }
    }

    #endregion

    #region IfUsage<T>

    public class IfUsage<T> : IExpression<T>
    {
        public readonly IExpression<T> Condition;
        public readonly IExpression<T> IfBody;
        public readonly IExpression<T> ElseBody;

        public IfUsage(IExpression<T> condition, IExpression<T> ifBody, IExpression<T> elseBody)
        {
            Condition = condition;
            IfBody = ifBody;
            ElseBody = elseBody;
        }

        public override string ToString()
        {
            return string.Format("(if {0} {1} {2})", Condition, IfBody, ElseBody);
        }

        public T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
            T conditionValue = Condition.Evaluate(localEnvironment, globalInfo);

            //if (!conditionValue.Equals(globalInfo.FalseValue))
            if (!globalInfo.ValueIsFalse(conditionValue))
            {
                return IfBody.Evaluate(localEnvironment, globalInfo);
            }
            else
            {
                return ElseBody.Evaluate(localEnvironment, globalInfo);
            }
        }
    }

    #endregion

    #region WhileUsage<T>

    public class WhileUsage<T> : IExpression<T>
    {
        public readonly IExpression<T> Condition;
        public readonly IExpression<T> Body;

        public WhileUsage(IExpression<T> condition, IExpression<T> body)
        {
            Condition = condition;
            Body = body;
        }

        public override string ToString()
        {
            return string.Format("(while {0} {1})", Condition, Body);
        }

        public T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
#if DEAD_CODE
            T conditionValue;
            T falseValue = globalInfo.FalseValue;

            for (; ; )
            {
                conditionValue = Condition.Evaluate(localEnvironment, globalInfo);

                if (conditionValue.Equals(falseValue))
                {
                    break;
                }

                Body.Evaluate(localEnvironment, globalInfo);
            }

            return conditionValue;
#else

            while (!globalInfo.ValueIsFalse(Condition.Evaluate(localEnvironment, globalInfo)))
            {
                Body.Evaluate(localEnvironment, globalInfo);
            }

            return globalInfo.FalseValue;
#endif
        }
    }

    #endregion

    #region SetUsage<T>

    public class SetUsage<T> : IExpression<T>
    {
        public readonly Variable<T> VariableName;
        public readonly IExpression<T> Expression;

        public SetUsage(Variable<T> variableName, IExpression<T> expression)
        {
            VariableName = variableName;
            Expression = expression;
        }

        public override string ToString()
        {
            return string.Format("(set {0} {1})", VariableName, Expression);
        }

        public T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
            T expressionValue = Expression.Evaluate(localEnvironment, globalInfo);

            // If the variable is not already defined in a local env, we may have to assign it to the global env.
            localEnvironment.AddBubbleDown(VariableName, expressionValue);
            return expressionValue;
        }
    }

    #endregion

    #region ExpressionList<T>

    public class ExpressionList<T>
    {
        public readonly List<IExpression<T>> Value;

        public ExpressionList()
        {
            Value = new List<IExpression<T>>();
        }

        public override string ToString()
        {
            return string.Join(" ", Value);
        }
    }

    #endregion

    #region BeginUsage<T>

    public class BeginUsage<T> : IExpression<T>
    {
        public readonly IExpression<T> FirstExpression;
        public readonly ExpressionList<T> ExpressionList;

        public BeginUsage(IExpression<T> firstExpression, ExpressionList<T> expressionList)
        {
            FirstExpression = firstExpression;
            ExpressionList = expressionList;
        }

        public override string ToString()
        {
            return string.Format("(begin {0} {1})", FirstExpression, ExpressionList);
        }

        public T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
            T result = FirstExpression.Evaluate(localEnvironment, globalInfo);

            foreach (var expression in ExpressionList.Value)
            {
                result = expression.Evaluate(localEnvironment, globalInfo);
            }

            return result;
        }
    }

    #endregion

    #region CondUsage<T>

    public class CondUsage<T> : IExpression<T>
    {
        public readonly List<KeyValuePair<IExpression<T>, IExpression<T>>> ExprPairList;

        public CondUsage(List<KeyValuePair<IExpression<T>, IExpression<T>>> exprPairList)
        {
            ExprPairList = exprPairList;
        }

        public T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
            //var falseValue = globalInfo.FalseValue;

            foreach (var exprPair in ExprPairList)
            {

                //if (!exprPair.Key.Evaluate(localEnvironment, globalInfo).Equals(falseValue))
                if (!globalInfo.ValueIsFalse(exprPair.Key.Evaluate(localEnvironment, globalInfo)))
                {
                    return exprPair.Value.Evaluate(localEnvironment, globalInfo);
                }
            }

            //return falseValue;
            return globalInfo.FalseValue;
        }
    }

    #endregion

    #region LetUsage<T>

    public class LetUsage<T> : IExpression<T>
    {
        public readonly List<KeyValuePair<Variable<T>, IExpression<T>>> Bindings;
        public readonly IExpression<T> Expression;

        public LetUsage(List<KeyValuePair<Variable<T>, IExpression<T>>> bindings, IExpression<T> expression)
        {
            Bindings = bindings;
            Expression = expression;
        }

        public T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
            var newEnvFrame = new EnvironmentFrame<T>(localEnvironment);

            foreach (var binding in Bindings)
            {
                newEnvFrame.Add(binding.Key, binding.Value.Evaluate(localEnvironment, globalInfo));
            }

            return Expression.Evaluate(newEnvFrame, globalInfo);
        }
    }

    #endregion

    #region LetStarUsage<T>

    public class LetStarUsage<T> : IExpression<T>
    {
        public readonly List<KeyValuePair<Variable<T>, IExpression<T>>> Bindings;
        public readonly IExpression<T> Expression;

        public LetStarUsage(List<KeyValuePair<Variable<T>, IExpression<T>>> bindings, IExpression<T> expression)
        {
            Bindings = bindings;
            Expression = expression;
        }

        public T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
#if DEAD_CODE
            var newEnvFrame = new EnvironmentFrame<T>(localEnvironment);

            foreach (var binding in Bindings)
            {
                newEnvFrame.Add(binding.Key, binding.Value.Evaluate(newEnvFrame, globalInfo));
            }

            return Expression.Evaluate(newEnvFrame, globalInfo);
#else
            // 2014/02/17 : This implementation does not support recursive definitions.
            var lastEnv = localEnvironment;

            foreach (var binding in Bindings)
            {
                var newEnvFrame = new EnvironmentFrame<T>(lastEnv);

                newEnvFrame.Add(binding.Key, binding.Value.Evaluate(lastEnv, globalInfo));
                lastEnv = newEnvFrame;
            }

            return Expression.Evaluate(lastEnv, globalInfo);
#endif
        }
    }

    #endregion

    #region OperatorUsage<T>

    public class OperatorUsage<T> : IExpression<T>
    {
        public readonly Name OperatorName;
        public readonly ExpressionList<T> ExpressionList;

        public OperatorUsage(Name operatorName, ExpressionList<T> expressionList)
        {
            OperatorName = operatorName;
            ExpressionList = expressionList;
        }

        public override string ToString()
        {

            if (ExpressionList.Value.Count == 0)
            {
                return string.Format("({0})", OperatorName);
            }

            return string.Format("({0} {1})", OperatorName, ExpressionList);
        }

        protected virtual bool TryGetExpectedNumArgs(IGlobalInfo<T> globalInfo, out int result)
        {

            if (IntegerOperatorKeeper.TwoArgumentOperators.ContainsKey(OperatorName.Value) ||
                IntegerOperatorKeeper.TwoArgumentPredicates.ContainsKey(OperatorName.Value))
            {
                result = 2;
                return true;
            }

            switch (OperatorName.Value)
            {
                case "print":
                    result = 1;
                    return true;

                case "=":
                    result = 2;
                    return true;

                default:

                    if (globalInfo.FunctionDefinitions.ContainsKey(OperatorName))
                    {
                        result = globalInfo.FunctionDefinitions[OperatorName].ArgList.Value.Count;
                        return true;
                    }
                    else if (globalInfo.MacroDefinitions != null && globalInfo.MacroDefinitions.ContainsKey(OperatorName))
                    {
                        result = globalInfo.MacroDefinitions[OperatorName].ArgumentCount;
                        return true;
                    }
                    else
                    {
                        result = 0;
                        return false;
                    }
            }
        }

        protected virtual string CheckArgTypes(List<T> evaluatedArguments)
        {
            return null;
        }

        protected virtual bool TryInvokeMacro(
            List<IExpression<T>> unevaluatedArguments,
            EnvironmentFrame<T> localEnvironment,
            IGlobalInfo<T> globalInfo,
            out T macroResult)
        {
            macroResult = default(T);
            return false;
        }

        protected virtual void UpdateStackTrace(EnvironmentFrame<T> oldEnvFrame, EnvironmentFrame<T> newEnvFrame,
            int line, int column)
        {
        }

        protected virtual T EvaluateAux(List<T> evaluatedArguments, EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
            int firstArgAsInt = (evaluatedArguments.Count > 0 && globalInfo.ValueIsInteger(evaluatedArguments[0]))
                ? globalInfo.ValueAsInteger(evaluatedArguments[0]) : 0;
            int secondArgAsInt = (evaluatedArguments.Count > 1 && globalInfo.ValueIsInteger(evaluatedArguments[1]))
                ? globalInfo.ValueAsInteger(evaluatedArguments[1]) : 0;

            if (IntegerOperatorKeeper.TwoArgumentOperators.ContainsKey(OperatorName.Value))
            {
                return globalInfo.IntegerAsValue(IntegerOperatorKeeper.TwoArgumentOperators[OperatorName.Value](firstArgAsInt, secondArgAsInt));
            }
            else if (IntegerOperatorKeeper.TwoArgumentPredicates.ContainsKey(OperatorName.Value))
            {
                return IntegerOperatorKeeper.TwoArgumentPredicates[OperatorName.Value](firstArgAsInt, secondArgAsInt) ? globalInfo.TrueValue : globalInfo.FalseValue;
            }

            switch (OperatorName.Value)
            {
                case "=":
                    return evaluatedArguments[0].Equals(evaluatedArguments[1]) ? globalInfo.TrueValue : globalInfo.FalseValue;

                case "print":
                    Console.WriteLine(evaluatedArguments[0]);
                    return evaluatedArguments[0];

                default:

                    if (globalInfo.FunctionDefinitions.ContainsKey(OperatorName))
                    {
                        // Evaluate a user-defined function.
                        var newEnvironment = new EnvironmentFrame<T>(globalInfo.DynamicScoping ? localEnvironment : globalInfo.GlobalEnvironment);

                        if (globalInfo.Debug)
                        {
                            UpdateStackTrace(localEnvironment, newEnvironment, OperatorName.Line, OperatorName.Column);
                        }

                        newEnvironment.Compose(globalInfo.FunctionDefinitions[OperatorName].ArgList.Value, evaluatedArguments);
                        return globalInfo.FunctionDefinitions[OperatorName].Body.Evaluate(newEnvironment, globalInfo);
                    }

                    throw new EvaluationException(
                        string.Format("EvaluateAux() : Unknown operator name '{0}'", OperatorName),
                        OperatorName.Line, OperatorName.Column);
            }
        }

        // This is virtual because Scheme.PrimOp overrides it.

        public virtual T Evaluate(EnvironmentFrame<T> localEnvironment, IGlobalInfo<T> globalInfo)
        {
            var actualNumArgs = ExpressionList.Value.Count;
            int expectedNumArgs;

            if (!TryGetExpectedNumArgs(globalInfo, out expectedNumArgs))
            {
                throw new EvaluationException(
                    string.Format("OperatorUsage : Unknown operator name '{0}'", OperatorName.Value),
                    OperatorName.Line, OperatorName.Column);
            }
            else if (expectedNumArgs >= 0 && actualNumArgs != expectedNumArgs)
            {
                throw new EvaluationException(
                    string.Format("OperatorUsage : Expected {0} argument(s) for operator '{1}', instead of the actual {2} argument(s)",
                        expectedNumArgs, OperatorName.Value, actualNumArgs),
                    OperatorName.Line, OperatorName.Column);
            }

            T macroResult;

            if (TryInvokeMacro(ExpressionList.Value, localEnvironment, globalInfo, out macroResult))
            {
                return macroResult;
            }

            var evaluatedArguments = ExpressionList.Value.Select(expr => expr.Evaluate(localEnvironment, globalInfo)).ToList();
            var argTypesErrorMessage = CheckArgTypes(evaluatedArguments);

            if (!string.IsNullOrEmpty(argTypesErrorMessage))
            {
                throw new EvaluationException(
                    string.Format("Operator '{0}': {1}", OperatorName.Value, argTypesErrorMessage),
                    OperatorName.Line, OperatorName.Column);
            }

            return EvaluateAux(evaluatedArguments, localEnvironment, globalInfo);
        }
    }

    #endregion

    #region IntegerOperatorKeeper

    public static class IntegerOperatorKeeper
    {
        public static readonly Dictionary<string, Func<int, int, bool>> TwoArgumentPredicates = new Dictionary<string, Func<int, int, bool>>();
        public static readonly Dictionary<string, Func<int, int, int>> TwoArgumentOperators = new Dictionary<string, Func<int, int, int>>();

        static IntegerOperatorKeeper()
        {
            TwoArgumentPredicates["<"] = (x, y) => x < y;
            //TwoArgumentPredicates[">"] = (x, y) => x > y;

            TwoArgumentOperators["+"] = (x, y) => x + y;
            TwoArgumentOperators["-"] = (x, y) => x - y;
            TwoArgumentOperators["*"] = (x, y) => x * y;
            TwoArgumentOperators["/"] = (x, y) => x / y;
        }
    }

    #endregion

    #region DoubleOperatorKeeper

    public static class DoubleOperatorKeeper
    {
        public static readonly Dictionary<string, Func<double, double>> OneArgumentOperators = new Dictionary<string, Func<double, double>>();
        public static readonly Dictionary<string, Func<double, double, bool>> TwoArgumentPredicates = new Dictionary<string, Func<double, double, bool>>();
        public static readonly Dictionary<string, Func<double, double, double>> TwoArgumentOperators = new Dictionary<string, Func<double, double, double>>();

        static DoubleOperatorKeeper()
        {
            OneArgumentOperators["exp"] = x => Math.Exp(x);
            OneArgumentOperators["ln"] = x => Math.Log(x);
            OneArgumentOperators["sin"] = x => Math.Sin(x);
            OneArgumentOperators["cos"] = x => Math.Cos(x);
            OneArgumentOperators["tan"] = x => Math.Tan(x);

            TwoArgumentPredicates["<"] = (x, y) => x < y;
            //TwoArgumentPredicates[">"] = (x, y) => x > y;

            TwoArgumentOperators["+"] = (x, y) => x + y;
            TwoArgumentOperators["-"] = (x, y) => x - y;
            TwoArgumentOperators["*"] = (x, y) => x * y;
            TwoArgumentOperators["/"] = (x, y) => x / y;
            TwoArgumentOperators["pow"] = (x, y) => Math.Pow(x, y);
            TwoArgumentOperators["atan2"] = (y, x) => Math.Atan2(y, x); // Note the reversed order of the parameters.
        }
    }

    #endregion

    #region GlobalInfoBase<T>

    public abstract class GlobalInfoBase<T> : IGlobalInfo<T>, IGlobalInfoOps
    {
        private readonly ITokenizer tokenizer;
        private readonly IParser parser;
        private readonly EnvironmentFrame<T> GlobalEnv = new EnvironmentFrame<T>(null);
        private readonly Dictionary<Name, FunctionDefinition<T>> FunctionDefs = new Dictionary<Name, FunctionDefinition<T>>();
        private readonly Random RNG = new Random();
        public bool DynamicScoping { get; set; }
        public bool Debug { get; set; }

        protected GlobalInfoBase(ITokenizer t, IParser p)
        {
            tokenizer = t;
            parser = p;
            DynamicScoping = false;
            Debug = false;
        }

        public ITokenizer Tokenizer
        {
            get
            {
                return tokenizer;
            }
        }

        public IParser Parser
        {
            get
            {
                return parser;
            }
        }

        public void Clear()
        {
            GlobalEnv.Dict.Clear();
            FunctionDefs.Clear();

            if (MacroDefinitions != null)
            {
                MacroDefinitions.Clear();
            }

            SetScoping(false);  // Set the scope rules to "static" rather than "dynamic".
            SetDebug(false);    // Turn debug mode off.
        }

        protected void Evaluate(string input)
        {
            var expr = Parser.Parse(Tokenizer.Tokenize(input)) as IExpression<T>;

            if (expr == null)
            {
                throw new Exception(string.Format("GlobalInfoBase.Evaluate() : Parse failed; input is: {0}", input));
            }

            expr.Evaluate(GlobalEnvironment, this);
        }

        public virtual string LoadPreset(string presetName)
        {
            throw new Exception(string.Format("LoadPreset() : Unknown preset name '{0}'.", presetName));
        }

        public virtual void LoadPresets()
        {
        }

        public abstract T FalseValue { get; }
        public abstract T TrueValue { get; }

        public virtual bool ValueIsFalse(T value)
        {
            return value.Equals(FalseValue);
        }

        public EnvironmentFrame<T> GlobalEnvironment
        {
            get
            {
                return GlobalEnv;
            }
        }

        public virtual Dictionary<Name, FunctionDefinition<T>> FunctionDefinitions
        {
            get
            {
                return FunctionDefs;
            }
        }

        public virtual Dictionary<Name, IMacroDefinition<T>> MacroDefinitions
        {
            get
            {
                return null;
            }
        }

        public abstract bool ValueIsInteger(T value);
        public abstract int ValueAsInteger(T value);
        public abstract T IntegerAsValue(int value);

        public Random RandomNumberGenerator
        {
            get
            {
                return RNG;
            }
        }

        public virtual bool SetScoping(bool dynamicScoping)
        {
            DynamicScoping = dynamicScoping;
            return true;
        }

        public virtual bool SetDebug(bool debug)
        {
            return false;
        }
    }

    #endregion
}


text:
layout: notes
title: time series
category: stat
---

{:toc}

# high-level

## basics

- usually assume points are equally spaced
- modeling - for understanding underlying process or predicting
- [nice blog](https://algorithmia.com/blog/introduction-to-time-series), [nice tutorial](https://www.itl.nist.gov/div898/handbook/pmc/section4/pmc442.htm), [Time Series for scikit-learn People](https://www.ethanrosenthal.com/2018/01/28/time-series-for-scikit-learn-people-part1/)
- *noise*, *seasonality* (regular / predictable fluctuations), *trend*, *cycle*
- multiplicative models: time series = trend * seasonality * noise
- additive model: time series = trend + seasonality + noise
- stationarity - mean, variance, and autocorrelation structure do not change over time
- **endogenous variable = x** = independent variable
- **exogenous variable = y** = dependent variable
- changepointe detection / [Change detection ](https://en.wikipedia.org/wiki/Change_detection) - tries to identify times when the probability distribution of a stochastic process or time series changes

## libraries

- [pandas has some great time-series functionality](https://tomaugspurger.github.io/modern-7-timeseries)
- [skits library](https://github.com/EthanRosenthal/skits) for forecasting

## high-level modelling

- common methods
  - decomposition - identify each of these components given a time-series
    - ex. loess, exponential smoothing
  - frequency-based methods - e.g. look at spectral plot
  - (AR) autoregressive models - linear regression of current value of one or more prior values of the series
  - (MA) moving-average models - require fitting the noise terms
  - (ARMA) box-jenkins approach
- moving averages
  - simple moving average - just average over a window
  - cumulative moving average - mean is calculated using previous mean
  - exponential moving average - exponentially weights up more recent points
- prediction (forecasting) models
  - autoregressive integrated moving average (arima)
    - assumptions: stationary model

# similarity measures

- [An Empirical Evaluation of Similarity Measures for Time Series Classification](https://arxiv.org/pdf/1401.3973.pdf) (serra et al. 2014)
  - lock-step measures (Euclidean distance, or any norm)
    - can resample to make them same length
  - feature-based measures (Fourier coefficients)
    - euclidean distance over all coefs is same as over time-series, but we usually filter out high-freq coefs
    - can also use wavelets
  - model-based measures (auto-regressive)
    - compare coefs of an AR (or ARMA) model
  - elastic measures
    - dynamic time warping = DTW - optimallt aligns in temporal domaub ti nubunuze accumulated cost
      - can also enforce some local window around points
      - Every index from the first sequence must be matched with one or more indices from the other sequence and vice versa
      - The first index from the first sequence must be matched with the first index from the other sequence (but it does not have to be its only match)
      - The last index from the first sequence must be matched with the last index from the other sequence (but it does not have to be its only match)
      - The mapping of the indices from the first sequence to indices from the other sequence must be monotonically increasing, and vice versa, i.e. if `j > i` are indices from the first sequence, then there must not be two indices `l > k` in the other sequence, such that index `i` is matched with index `l` and index `j` is matched with index `k` , and vice versa
    - edit distance EDR
    - time-warped edit distance - TWED
    - minimum jump cost - MJC

# [book1](https://www.stat.tamu.edu/~suhasini/teaching673/time_series.pdf) (A course in Time Series Analysis) + [book2](http://home.iitj.ac.in/~parmod/document/introduction%20time%20series.pdf) (Intro to Time Series and Forecasting)

## ch 1

- when errors are dependent, very hard to distinguish noise from signal
- usually in time-series analysis, we begin by de-trending the data and analyzing the residuals
  - ex. assume linear trend or quadratic trend and subtract that fit (or could include sin / cos for seasonal behavior)
  - ex. look at the differences instead of the points (nth order difference removes nth order polynomial trend). However, taking differences can introduce dependencies in the data
  - ex. remove trend using sliding window (maybe with exponential weighting)
- periodogram - in FFT, this looks at the magnitude of the coefficients (but loses the phase information)

## ch 2 - stationary time series

- in time series, we never get iid data
- instead we make assumptions
  - ex. the process has a constant mean (a type of stationarity)
  - ex. the dependencies in the time-series are short-term
- autocorrelation plots: plot correlation of series vs series offset by different lags
- formal definitions of stationarity for time series $\{X_t\}$
  - **strict stationarity** - the distribution is the same across time
  - **second-order / weak stationarity** -  mean is constant for all t and, for any t and k, the covariance between $X_t$ and $X_{t+k}$ only depends on the lag difference k
    - In other words, there exists a function $c: \mathbb Z \to \mathbb R$ such that for all t and k we have $c(k) = \text{cov} (X_t, X_{t+k})$
    - strict stationary and $E|X_T^2| < \infty \implies$ second-order stationary
  - **ergodic** - stronger condition, says samples approach the expectation of functions on the time series: for any function $g$ and shift $\tau_1, ... \tau_k$:
    - $\frac 1 n \sum_t g(X_t, ... X_{t+\tau_k}) \to \mathbb E [g(X_0, ..., X_{t+\tau_k} )]$
- **causal** - can predict given only past values (for Gaussian processes no difference)

## ch 3 - linear time series

**note: can just assume all have 0 mean (otherwise add a constant)**

- **AR model** $AR(p)$:  $$ X_t = \sum_{i=1}^p \phi_i X_{t-i}+ \varepsilon_t $$
  - $\phi_1, \ldots, \phi_p$ are parameters
  - $\varepsilon_t$ is white noise
  - stationary assumption places constraints on param values (e.g. processes in the $AR(1)$ model with $|\phi_1| \ge 1$ are not stationary)
  - looks just like linear regression, but is more complex
    - if we don't account for issues, things can go wrong
      - model will not be stationary
      - model may be misspecified
      - $E(\epsilon_t|X_{t-p}) \neq 0$
    - this represents a set of difference equations, and as such, must have a solution
  - ex. $AR(1)$ model - if $|\phi| < 0$, then soln is in terms of past values of {$\epsilon_t$}, otherwise it is in terms of future values
    - ex. simulating - if we know $\phi$ and $\{\epsilon_t\}$, we still need to use the backshift operator to solve for  $\{ X_t \}$
  - ex. $AR(p)$ model - if $\sum_j |\phi_j|$< 1, and $\mathbb E |\epsilon_t| < \infty$, then will have a causal stationary solution
  - **backshift operator** $B^kX_t=X_{t-k}$
    - solving requires using the backshift operator, because we need to solve for what all the residuals are
  - **characteristic polynomial** $\phi(a) = 1 - \sum_{j=1}^p \phi_j a^j$
    - $\phi(B) X_t = \epsilon_t$
    - $X_t=\phi(B)^{-1} \epsilon_t$
  - can represent $AR(p)$ as a vector $AR(1)$ using the vector $\bar X_t = (X_t, ..., X_{t-p+1})$
  - note: can reparametrize in terms of frequencies
- **MA model** $MA(q)$: $ X_t = \sum_{i=1}^q \theta_i \varepsilon_{t-i} + \varepsilon_t$
  - $\theta_1 ... \theta_q$ are params
  - $\varepsilon_t$, $\varepsilon_{t-1}$ are white noise error terms
  - harder to fit, because the lagged error terms are not visible (also means can't make preds on new time-series)
  - $E[\epsilon_t] = 0$, $Var[\epsilon_t] = 1$
  - much harder to estimate these parameters
  - $X_t = \theta (B) \epsilon_t$ (assuming $\theta_0=1$)
- **ARMA model**: $ARMA(p, q)$: $X_t = \sum_{i=1}^p \phi_i X_{t-i} + \sum_{i=1}^q \theta_i \varepsilon_{t-i} + \varepsilon_t$
  - $\{X_t\}$ is stationary
  - $\phi (B) X_t = \theta(B) \varepsilon_t$
  - $\phi(B) = 1 - \sum_{j=1}^p \phi_j B^j$
  - $\theta(B) = 1 + \sum_{j=1}^{q}\theta_jz^j$
  - **causal** if $\exists \{ \psi_j \}$ such that $X_t = \sum_{j=0}^\infty \psi_j Z_{t-j}$ for all t

- **ARIMA model**: $ARIMA(p, d, q)$: - generalizes ARMA model to non-stationarity (using differencing)

## ch 4 + 8 - the autocovariance function + parameter estimation

- estimation
  - pure autoregressive
    - Yule-walker
    - Burg estimation - minimizing sums of squares of forward and backward one-step prediction errors with respect to the coefficients
  - when $q > 0$
    - innovations algorithm
    - hannan-rissanen algorithm
- autocovariance function: {$\gamma(k): k \in \mathbb Z$} where $\gamma(k) = \text{Cov}(X_{t+h}. X_t) =  \mathbb E (X_0 X_k)$ (assuming mean 0)
- ![Screen Shot 2020-01-11 at 5.29.15 PM](../assets/durbin-levinson.png)
- **Yule-Walker equations** (assuming AR(p) process): $\mathbb E (X_t X_{t-k}) = \sum_{j=1}^p \phi_j \mathbb E (X_{t-j} X_{t-k}) + \underbrace{\mathbb E (\epsilon_tX_{t-k})}_{=0} = \sum_{j=1}^p \phi_j \mathbb E (X_{t-j} X_{t-k})$
  - ex. MA covariance becomes 0 with lag > num params
- can rewrite the Yule-Walker equations

  - $\gamma(i) = \sum_{j=1}^p \phi_j \gamma(i -j)$
  - $\underline\gamma_p = \Gamma_p \underline \phi_p$
    - $(\Gamma_p)_{i, j} = \gamma(i - j)$
    - $\hat{\Gamma}_p$ is nonegative definite (and nonsingular if there is at least one nonzero $Y_i$)
  - $\underline \gamma_p = [\gamma(1), ..., \gamma(p)]$
  - $\underline \phi_p = (\phi_1, ..., \phi_p)$
    - this minimizes the mse $\mathbb E [X_{t+1} - \sum_{j=1}^p \phi_j X_{t+1-j}]^2$
- use estimates to solve: $\hat{\underline \phi}_p = \hat \Sigma_p^{-1} \hat{\underline r}_p $
- the innovations algorithm
  - set $\hat X_1 = 0$
  - **innovations** = one-step prediction errors $U_n = X_n - \hat X _n$
- **mle** (ch 5.2)
  - eq. 5.2.9: Gaussian likelihood for an ARMA process
  - $r_n = \mathbb E[(W_{n+1} - \hat W_{n+1})^2]$

# multivariate time-series ch 7

- vector-valued time-series has dependencies between variables across time
  - just modeling as univariate fails to take into account possible dependencies between the series

# neural modeling

- see [pytorch-forecasting](https://pytorch-forecasting.readthedocs.io/en/latest/api/pytorch_forecasting.models.html#module-pytorch_forecasting.models) for some new state-of-the-art models

redpajama_set_name: RedPajamaGithub


text:
//
// Mono.Security.Protocol.Ntlm.Type1Message - Negotiation
//
// Authors: Sebastien Pouliot <sebastien@ximian.com>
//          Jeffrey Stedfast <jeff@xamarin.com>
//
// Copyright (c) 2003 Motus Technologies Inc. (http://www.motus.com)
// Copyright (c) 2004 Novell, Inc (http://www.novell.com)
// Copyright (c) 2013-2020 .NET Foundation and Contributors
//
// References
// a.	NTLM Authentication Scheme for HTTP, Ronald Tschalär
//	http://www.innovation.ch/java/ntlm.html
// b.	The NTLM Authentication Protocol, Copyright © 2003 Eric Glass
//	http://davenport.sourceforge.net/ntlm.html
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.Text;

namespace MailKit.Security.Ntlm {
	class Type1Message : MessageBase
	{
		internal static readonly NtlmFlags DefaultFlags = NtlmFlags.NegotiateNtlm | NtlmFlags.NegotiateOem | NtlmFlags.NegotiateUnicode | NtlmFlags.RequestTarget;

		string domain;
		string host;

		public Type1Message (string hostName, string domainName) : base (1)
		{
			Flags = DefaultFlags;
			Domain = domainName;
			Host = hostName;
		}

		public Type1Message (byte[] message, int startIndex, int length) : base (1)
		{
			Decode (message, startIndex, length);
		}

		public string Domain {
			get { return domain; }
			set {
				if (string.IsNullOrEmpty (value)) {
					Flags &= ~NtlmFlags.NegotiateDomainSupplied;
					value = string.Empty;
				} else {
					Flags |= NtlmFlags.NegotiateDomainSupplied;
				}

				domain = value;
			}
		}

		public string Host {
			get { return host; }
			set {
				if (string.IsNullOrEmpty (value)) {
					Flags &= ~NtlmFlags.NegotiateWorkstationSupplied;
					value = string.Empty;
				} else {
					Flags |= NtlmFlags.NegotiateWorkstationSupplied;
				}

				host = value;
			}
		}

		public Version OSVersion {
			get; set;
		}

		void Decode (byte[] message, int startIndex, int length)
		{
			int offset, count;

			ValidateArguments (message, startIndex, length);

			Flags = (NtlmFlags) BitConverterLE.ToUInt32 (message, startIndex + 12);

			// decode the domain
			count = BitConverterLE.ToUInt16 (message, startIndex + 16);
			offset = BitConverterLE.ToUInt16 (message, startIndex + 20);
			domain = Encoding.UTF8.GetString (message, startIndex + offset, count);

			// decode the workstation/host
			count = BitConverterLE.ToUInt16 (message, startIndex + 24);
			offset = BitConverterLE.ToUInt16 (message, startIndex + 28);
			host = Encoding.UTF8.GetString (message, startIndex + offset, count);

			if (offset == 40) {
				// decode the OS Version
				int major = message[startIndex + 32];
				int minor = message[startIndex + 33];
				int build = BitConverterLE.ToUInt16 (message, startIndex + 34);

				OSVersion = new Version (major, minor, build);
			}
		}

		public override byte[] Encode ()
		{
			int versionLength = OSVersion != null ? 8 : 0;
			int hostOffset = 32 + versionLength;
			int domainOffset = hostOffset + host.Length;

			var message = PrepareMessage (32 + domain.Length + host.Length + versionLength);

			message[12] = (byte) Flags;
			message[13] = (byte)((uint) Flags >> 8);
			message[14] = (byte)((uint) Flags >> 16);
			message[15] = (byte)((uint) Flags >> 24);

			message[16] = (byte) domain.Length;
			message[17] = (byte)(domain.Length >> 8);
			message[18] = message[16];
			message[19] = message[17];
			message[20] = (byte) domainOffset;
			message[21] = (byte)(domainOffset >> 8);

			message[24] = (byte) host.Length;
			message[25] = (byte)(host.Length >> 8);
			message[26] = message[24];
			message[27] = message[25];
			message[28] = (byte) hostOffset;
			message[29] = (byte)(hostOffset >> 8);

			if (OSVersion != null) {
				message[32] = (byte) OSVersion.Major;
				message[33] = (byte) OSVersion.Minor;
				message[34] = (byte)(OSVersion.Build);
				message[35] = (byte)(OSVersion.Build >> 8);
				message[36] = 0x00;
				message[37] = 0x00;
				message[38] = 0x00;
				message[39] = 0x0f;
			}

			var hostName = Encoding.UTF8.GetBytes (host.ToUpperInvariant ());
			Buffer.BlockCopy (hostName, 0, message, hostOffset, hostName.Length);

			var domainName = Encoding.UTF8.GetBytes (domain.ToUpperInvariant ());
			Buffer.BlockCopy (domainName, 0, message, domainOffset, domainName.Length);

			return message;
		}
	}
}


text: __all__ = ["filters", "filtering", "anomaly", "grouping"]


text:
package com.palantir.timelock.history.models;

import com.google.common.collect.ImmutableMap;
import com.palantir.paxos.NamespaceAndUseCase;
import java.util.Map;
import org.immutables.value.Value;

@Value.Immutable
public interface ConsolidatedPaxosHistoryOnSingleNode {

    @Value.Parameter
    Map<NamespaceAndUseCase, ConsolidatedLearnerAndAcceptorRecord> records();

    static ConsolidatedPaxosHistoryOnSingleNode of(
            Map<NamespaceAndUseCase, ConsolidatedLearnerAndAcceptorRecord> records) {
        return ImmutableConsolidatedPaxosHistoryOnSingleNode.of(records);
    }

    default ConsolidatedLearnerAndAcceptorRecord getRecordForNamespaceAndUseCase(
            NamespaceAndUseCase namespaceAndUseCase) {
        return records().getOrDefault(namespaceAndUseCase, ConsolidatedLearnerAndAcceptorRecord.of(ImmutableMap.of()));
    }
}


text:
package br.edu.coo2015.ep2.model;

public class AutenticacaoException extends Exception {

	private static final long serialVersionUID = 1L;

	public AutenticacaoException() {
	}

	public AutenticacaoException(String mensagem) {
		super(mensagem);
	}
}


text:
package edw.repository;

import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name = "zcrmprodh")
public class ZcrmProdhDao extends AbstractEntity {

    protected String spras;
    protected String prodh;
	protected String vtext;

    public String getSpras() {
		return spras;
	}
	public void setSpras(String spras) {
		this.spras = spras;
	}
	public String getProdh() {
		return prodh;
	}
	public void setProdh(String prodh) {
		this.prodh = prodh;
	}
	public String getVtext() {
		return vtext;
	}
	public void setVtext(String vtext) {
		this.vtext = vtext;
	}

}


text:
/*
author: Krzysztof Sopyla
mail: krzysztofsopyla@gmail.com
License: MIT
web page: http://wmii.uwm.edu.pl/~ksopyla/projects/svm-net-with-cuda-kmlib/
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using KMLib.Helpers;

namespace KMLib.GPU.GPUEvaluators
{
    public class CuExpChiERTILPEvaluator : CuEvaluator
    {
        private GASS.CUDA.Types.CUdeviceptr valsPtr;
        private GASS.CUDA.Types.CUdeviceptr idxPtr;
        private GASS.CUDA.Types.CUdeviceptr vecLengthPtr;
        private GASS.CUDA.Types.CUdeviceptr selfSumPtr;

        private float gamma;

        /// <summary>
        /// how many threads are assigned for row
        /// </summary>
        private int ThreadsPerRow=4;

        /// <summary>
        /// how many non zero elements are loaded in cuda kernel
        /// </summary>
        private int Prefetch=2;
        private int vectorSelfSumParamOffset;

        public CuExpChiERTILPEvaluator(float gamma)
        {
            this.gamma = gamma;
            cudaEvaluatorKernelName = "expChi2EllpackEvaluator";
            cudaModuleName = "KernelsEllpack.cubin";

        }

        protected override void SetCudaEvalFunctionParams()
        {
            cuda.SetFunctionBlockShape(cuFuncEval, evalThreads, 1, 1);

            int offset = 0;
            cuda.SetParameter(cuFuncEval, offset, valsPtr.Pointer);
            offset += IntPtr.Size;
            cuda.SetParameter(cuFuncEval, offset, idxPtr.Pointer);
            offset += IntPtr.Size;

            cuda.SetParameter(cuFuncEval, offset, vecLengthPtr.Pointer);
            offset += IntPtr.Size;

            cuda.SetParameter(cuFuncEval, offset, selfSumPtr.Pointer);
            offset += IntPtr.Size;

            cuda.SetParameter(cuFuncEval, offset, alphasPtr.Pointer);
            offset += IntPtr.Size;

            cuda.SetParameter(cuFuncEval, offset, labelsPtr.Pointer);
            offset += IntPtr.Size;

            kernelResultParamOffset = offset;
            cuda.SetParameter(cuFuncEval, offset, evalOutputCuPtr[0].Pointer);
            offset += IntPtr.Size;

            cuda.SetParameter(cuFuncEval, offset, (uint)sizeSV);
            offset += sizeof(int);

            vectorSelfSumParamOffset = offset;
            cuda.SetParameter(cuFuncEval, offset, 0);
            offset += sizeof(int);

            cuda.SetParameter(cuFuncEval, offset, gamma);
            offset += sizeof(float);

            texSelParamOffset = offset;
            cuda.SetParameter(cuFuncEval, offset, 1);
            offset += sizeof(int);

            cuda.SetParameterSize(cuFuncEval, (uint)offset);
        }

        protected override void SetCudaEvalFuncParamsForVector(SparseVec vec)
        {
            cuda.SetParameter(cuFuncEval, vectorSelfSumParamOffset, vec.Values.Sum());
        }

        public override void Init()
        {
            base.Init();

             SetCudaDataForERTILP();

             SetCudaEvalFunctionParams();
        }

        private void SetCudaDataForERTILP()
        {

            float[] vecVals;
            int[] vecColIdx;
            int[] vecLenght;

            evalBlocks = (int)Math.Ceiling((ThreadsPerRow * sizeSV + 0.0) / evalThreads);
            int align = ThreadsPerRow * Prefetch;
            CudaHelpers.TransformToERTILPFormat(out vecVals, out vecColIdx, out vecLenght, TrainedModel.SupportElements, align, ThreadsPerRow);

            float[] selfSum = TrainedModel.SupportElements.AsParallel().Select(c => c.Values.Sum()).ToArray();

            //copy data to device, set cuda function parameters
            valsPtr = cuda.CopyHostToDevice(vecVals);
            idxPtr = cuda.CopyHostToDevice(vecColIdx);
            vecLengthPtr = cuda.CopyHostToDevice(vecLenght);

            selfSumPtr = cuda.CopyHostToDevice(selfSum);

        }

        public void Dispose()
        {
            if (cuda != null)
            {

                cuda.Free(selfSumPtr);
                selfSumPtr.Pointer = IntPtr.Zero;

                DisposeResourses();

                cuda.UnloadModule(cuModule);
                base.Dispose();
                cuda.Dispose();
                cuda = null;
            }
        }

    }
}


text:
package in.manrajsingh.listviewexample;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Created by manraj singh on 2/9/2016.
 */
public class MyAdapter extends ArrayAdapter<String> {
    public MyAdapter(Context context, String[] values) {
        super(context, R.layout.row_layout_2,values);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater theInflater = LayoutInflater.from(getContext());
        View theView = theInflater.inflate(R.layout.row_layout_2, parent, false);
        String tv = getItem(position);
        TextView tV = (TextView) theView.findViewById(R.id.textView1);
        tV.setText(tv);
        ImageView iv = (ImageView) theView.findViewById(R.id.iv1);
        iv.setImageResource(R.drawable.dot);
        return theView;
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ru_RU">
<context>
    <name>main</name>
    <message>
        <location filename="../main.qml" line="199"/>
        <source>When the communism will come, everything'll be fuckin A!
It will come very soon - we just only need to wait!
All the stuff will be for free, everything will be so cool!
There will probably no need to even die no matter what!</source>
        <translation>А при коммунизме всё будет заебись!
Он наступит скоро - надо только ждать!
Там всё будет бесплатно, там всё будет в кайф!
Там наверное вообще не надо будет умирать!</translation>
    </message>
    <message>
        <location filename="../main.qml" line="208"/>
        <source>I woke up after midnight and realised - IT DOES!
Everything goes according to the plan.</source>
        <translation>Я проснулся среди ночи и понял, что - ВСЁ!
Всё идёт по плану.</translation>
    </message>
    <message>
        <location filename="../main.qml" line="215"/>
        <source>Egor Letov</source>
        <translation>Егор Летов</translation>
    </message>
    <message>
        <location filename="../main.qml" line="220"/>
        <source>Simple button</source>
        <translation>Простая кнопка</translation>
    </message>
    <message>
        <location filename="../main.qml" line="222"/>
        <source>Some output into console</source>
        <translation>Такой-то вывод в консоль</translation>
    </message>
    <message>
        <location filename="../main.qml" line="225"/>
        <source>Some tooltip</source>
        <translation>Такое-то всплывающее сообщение</translation>
    </message>
    <message>
        <location filename="../main.qml" line="242"/>
        <source>key</source>
        <translation>ключ</translation>
    </message>
    <message>
        <location filename="../main.qml" line="243"/>
        <source>game</source>
        <translation>игра</translation>
    </message>
    <message>
        <location filename="../main.qml" line="244"/>
        <source>sickle</source>
        <translation>серп</translation>
    </message>
    <message>
        <location filename="../main.qml" line="245"/>
        <source>hammer</source>
        <translation>молот</translation>
    </message>
    <message>
        <location filename="../main.qml" line="246"/>
        <source>star</source>
        <translation>звезда</translation>
    </message>
    <message>
        <location filename="../main.qml" line="250"/>
        <source>lantern</source>
        <translation>фонарь</translation>
    </message>
</context>
</TS>


text:
"use strict";

var React = require("../react");
var RadioItemTemplate = React.createClass({
    displayName: "RadioItemTemplate",

    render: function render() {
        var _props = this.props;
        var label = _props.label;
        var labelHTML = _props.labelHTML;
        var id = _props.id;

        label = labelHTML ? React.createElement("span", { dangerouslySetInnerHTML: { __html: labelHTML } }) : label;

        return React.createElement(
            "div",
            { className: "radio" },
            React.createElement(
                "label",
                null,
                this.props.children,
                label
            )
        );
    }
});
module.exports = RadioItemTemplate;


text:
VIEWS="/var/lib/ambari-server/resources/views"
STACK=""
FQDN=$(hostname -f)
CLUSTER_NAME=""
CURL='curl'
USERNAME="admin"
PASSWORD="admin"
agent="store-installer"
VERSION="0.1.5"
USE_DEMO_SERVER=no

#read -d '' data << EOF
#[{
#"ViewInstanceInfo" : { "label" : "Ambari Store", "description" : "Ambari Application Store",
#"properties" : {"amstore.ambari.cluster.url":"http://lake01.cloud.hortonworks.com:8080","amstore.ambari.cluster.password":"hortonworks","amstore.ambari.local.password":"admin","amstore.ambari.cluster.username":"remoteambari","amstore.ambari.local.username":"admin","amstore.ambari.local.url":"http://localhost:8080" } } }]
#EOF

function create_instance2() {
curl -u admin:admin -X POST -H "X-Requested-By: ambari" -d "${data}" http://localhost:8080/api/v1/views/AMBARI-STORE/versions/${VERSION}/instances/store
}

function usage() {

echo '
Usage: install.sh <options>
    -u <username>   Ambari administrator username. Defaults to "admin"
    -p <password>   Ambari administrator password. Defaults to "admin".
'
}

while getopts ":u:p:d" opt; do
	case "$opt" in
	u)	USERNAME=${OPTARG};;
	p)	PASSWORD=${OPTARG};;
	d)	USE_DEMO_SERVER=yes;;
	\?)	echo "Invalid option: -$OPTARG" >&2; usage; exit 1;;
	esac
done

CREDENTIALS="$USERNAME:$PASSWORD"
CURL="$CURL -u $CREDENTIALS"

function check_ambari(){
	response=$( $CURL -i http://localhost:8080/api/v1/clusters 2>&1)

	if [[ "$response" == *"HTTP/1.1 403 Bad credentials"* ]]; then
		echo "ERROR: Invalid credentials."
		usage
		exit 1

	elif [[ "$response" != *"HTTP/1.1 200 OK"* ]]
	then
		echo "ERROR: Failed connecting to Ambari. Ensure that the server is started. Error: $response"
		usage
		exit 1
	fi
}

function check_administrator_access() {
	isadmin=$( $CURL --silent http://localhost:8080/api/v1/users/${USERNAME} | python -c 'import sys,json; print json.load( sys.stdin )["Users"]["admin"]')
	if [[ "$isadmin" != "True" ]]; then
		echo "ERROR: User ${USERNAME} does not have administrator privileges."
		exit 1
	fi
}

function get_cluster_name() {
	response=$( $CURL -i http://localhost:8080/api/v1/clusters 2>&1)

	if [[ $response == *"HTTP/1.1 200 OK"* ]]
       then
		# Run curl without headers (no -i)
		CLUSTER_NAME=$( $CURL --silent http://localhost:8080/api/v1/clusters | python -c 'import sys,json; print json.load( sys.stdin )["items"][0]["Clusters"]["cluster_name"]')
		exit 1
	else
		echo "ERROR: Failed connecting to http://localhost:8080/api/v1/clusters. Error: $response"
			exit 1
    fi
}

function create_instance() {

data='[ { "ViewInstanceInfo" : { "label": "Ambari Store", "description": "Ambari Application Store",
"properties": {
	"amstore.ambari.local.username" : "_USERNAME_",
	"amstore.ambari.local.password" : "_PASSWORD_"
}
  } } ] '
data=$(  echo $data | sed "s/_USERNAME_/${USERNAME}/" )
data=$(  echo $data | sed "s/_PASSWORD_/${PASSWORD}/" )
$CURL -H "X-Requested-By: $agent" -X POST -d "${data}"  "http://localhost:8080/api/v1/views/AMBARI-STORE/versions/${VERSION}/instances/store"
}

function reconfigure_instance() {
$CURL -H "X-Requested-By: $agent" -X POST "http://localhost:8080/api/v1/views/AMBARI-STORE/versions/${VERSION}/instances/store/resources/taskmanager/reconfigure"
}

function install_agent() {
   rm -rf "/var/lib/ambari-server/resources/stacks/HDP/2.1/services/STOREAGENT"
   cp -rf "agent/STOREAGENT" "/var/lib/ambari-server/resources/stacks/HDP/2.1/services"
}

function create_agent() {

  # Create service
  $CURL -H "X-Requested-By: $agent" --silent -X POST -d '[ { "ServiceInfo" : { "service_name": "STOREAGENT"
  } } ] ' http://localhost:8080/api/v1/clusters/$CLUSTER_NAME/services

  # Create service component
  $CURL -H "X-Requested-By: $agent" --silent -X POST  http://localhost:8080/api/v1/clusters/$CLUSTER_NAME/services/STOREAGENT/components/STORE_CLIENT

  # Create host component
  $CURL -H "X-Requested-By: $agent" --silent -X POST http://localhost:8080/api/v1/clusters/$CLUSTER_NAME/hosts/$FQDN/host_components/STORE_CLIENT

  # Install agent on all hosts
  $CURL -H "X-Requested-By: $agent" --silent -X PUT -d '[ { "RequestInfo": { "context": "Install Store Agent Client" }, "Body" : { "ServiceInfo": { "state": "INSTALLED" }
  } } ] ' http://localhost:8080/api/v1/clusters/$CLUSTER_NAME/services/STOREAGENT

  # Configure client (not necessary yet)
  #$CURLH -X POST  -d
  data='[
  {
  "RequestInfo" : {
    "command" : "CONFIGURE",
    "context" : "Config Test Srv Client"
  },
  "Requests/resource_filters": [{
    "service_name" : "TESTSRV",
    "component_name" : "TEST_CLIENT",
    "hosts" : "c6403.ambari.apache.org"
  }]
 }
}]'  # http://localhost:8080/api/v1/clusters/$CLUSTER_NAME/requests

}

function delete_instance() {
$CURL -H "X-Requested-By: $agent" -X DELETE http://localhost:8080/api/v1/views/AMBARI-STORE/versions/$VERSION/instances/store
}

function wait_for_ambari() {
# poll for 60s or until we get a response
timeout=60
while [[ $timeout -ne 0 ]]; do

  status=$( $CURL --silent -i --connect-timeout 1 --max-time 1 http://localhost:8080/api/v1/clusters)
  if [[ $status == *"HTTP/1.1 200 OK"* ]]
       then
          break
  fi
  sleep 1
  timeout=$((timeout -1 ))
done
echo "Ambari ready."

}

# Check that we have a local Ambari
check_ambari

# Check the user is an administrator
check_administrator_access

# Get cluster name, serves as validation of settings also.
#get_cluster_name

rm -rf "${VIEWS}/work/AMBARI-STORE{$VERSION}"
rm -f "$VIEWS/ambari-store-$VERSION.jar"
cp -f target/ambari-store-$VERSION.jar "$VIEWS"
delete_instance
#install_agent

ambari-server restart
echo "Waiting for server to accept requests"
wait_for_ambari

# Forget about agent, a Views server won't allow it.
#echo "Installing agent service"
#create_agent
echo "Creating view instance"
if [[ "${USE_DEMO_SERVER}" == "yes" ]]; then
	create_instance2
else
	create_instance
fi

#Couldn't do in deploy() so doing here.
reconfigure_instance
echo ""
echo "The store is installed at:"
echo "http://$FQDN:8080/#/main/views/AMBARI-STORE/$VERSION/store"


text:
Rails.application.routes.draw do

  # --------------------------------------------------------------------------- #
  # The Web application                                                         #
  # --------------------------------------------------------------------------- #

  root "walkthrough#index"

  scope "walkthrough" do
    get "court/:id" => "walkthrough#court", as: :court
    get "citation/:id"=> "walkthrough#citation", as: :citation
    get "person/:id" => "walkthrough#person", as: :person
    post "search" => "walkthrough#search"
    post "confirm_birthday" => "walkthrough#confirm_birthday"
  end

  get "help/attorneys" => "walkthrough#find_attorneys"
  get "help/community-service" => "walkthrough#community_service"

  # --------------------------------------------------------------------------- #
  # The SMS API                                                                 #
  # --------------------------------------------------------------------------- #

  post "texts/incoming" => "text_messages#receive"
  post "texts/report" => "text_messages#report"
  get "texts/callback" => "text_messages#callback"
  post "texts/callback" => "text_messages#callback"
  post "texts/send_reminder" => "text_messages#send_reminder"
  get "geodata/muny" => "geo_data#municipalities"

end


text:
using System;
using System.Collections.Generic;
using System.Linq;

namespace Filter_Students_by_Email_Domain
{
    public class FilterStudentsByEmailDomain
    {
        public static void Main()
        {
            var students = new List<string>();

            while (true)
            {
                var input = Console.ReadLine();

                if (input.Equals("END"))
                {
                    break;
                }
                else
                {
                    students.Add(input);
                }
            }

            students.Select(x =>
            {
                var tokens = x.Split();
                var firstName = tokens[0];
                var secondName = tokens[1];
                var email = tokens[2];

                return new { firstName, secondName, email };
            }).Where(x => x.email.EndsWith("gmail.com")).ToList().ForEach(x => Console.WriteLine($"{x.firstName} {x.secondName}"));
        }
    }
}


text:
layout: docs
title: The many modules of AckCord
position: 2
---

# {{page.title}}
While the modules listed at the start are the main modules you want to depend on, AckCord has many more if you feel that you don't need the full package.

Here is a map of all the modules, and how they depend on each other
```
      +----> voice -----------------------> lavaplayer-core -+
      |                                         ^            |
      |                                         |            v
 data +----> gateway --> core ------------------+-------> ackcord
      |                   ^                     |            ^
      |                   |                     v            |
      +----> requests ----+-> commands ---> commands-core ---+
```

{% assign versions = site.data.versions %}

**Make sure to add the following line to your SBT file :**
```scala
resolvers += Resolver.JCenterRepository
```

---

## ackcord-data
```scala
libraryDependencies += "net.katsstuff" %%% "ackcord-data" % "{{versions.ackcord}}"
```
Provides access to all the data objects, encoders and decoders used by AckCord. This module is also crosscompiled for Scala.Js. Wonderful if you want to build a web panel for your bot in Scala, and don't want to redefine all the data objects.

## ackcord-requests
```scala
libraryDependencies += "net.katsstuff" %% "ackcord-rest" % "{{versions.ackcord}}"
```
Contains all the requests in AckCord.

## ackcord-gateway
```scala
libraryDependencies += "net.katsstuff" %% "ackcord-gateway" % "{{versions.ackcord}}" //The gateway module of AckCord
```
Contains the code for the AckCord gateway implementation. Depend on this if you want to build custom logic from the gateway and on. You might want to consider `ackcord-util` instead though.

## ackcord-voice
```scala
libraryDependencies += "net.katsstuff" %% "ackcord-voice" % "{{versions.ackcord}}"
```
Contains all the code for the voice stuff in AckCord.

## ackcord-commands
```scala
libraryDependencies += "net.katsstuff" %% "ackcord-commands" % "{{versions.ackcord}}"
```
The base commands API module. Does not work without an implementation.

## ackcord-core
```scala
libraryDependencies += "net.katsstuff" %% "ackcord-core" % "{{versions.ackcord}}"
```
The low level API module of AckCord. Provides the in memory cache.

## ackcord-commands-core
```scala
libraryDependencies += "net.katsstuff" %% "ackcord-commands-core" % "{{versions.ackcord}}"
```
Provides an implementation for the commands module using core.

## ackcord-lavaplayer-core
```scala
libraryDependencies += "net.katsstuff" %% "ackcord-lavaplayer-core" % "{{versions.ackcord}}"
```
Provides an implementation to the the voice module using lavaplayer and core.

To use, first create an instance of the `LavaplayerHandler` actor. This actor should be shared for an entire guild. Check the objects in the companion object of `LavaplayerHandler` for the valid messages you can send it.

## ackcord
```scala
libraryDependencies += "net.katsstuff" %% "ackcord" % "{{versions.ackcord}}"
```
The high level API, includes all the other modules.


text:
using System;
using System.Web.Routing;

namespace AnglicanGeek.Mvc
{
    public interface IRouteRegistrar
    {
        void RegisterRoutes(RouteCollection routes);
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id ="@+id/movie_poster"
        android:scaleType="centerCrop"
        android:adjustViewBounds="true"
        />
</FrameLayout>


text:
package net.harmonytheory.apt.scanner;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.util.ElementScanner6;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.JavaFileObject;

import org.mvel2.templates.TemplateRuntime;

/**
 * スキャナ基底クラス。
 * @author suppi~
 */
public abstract class ScannerBase extends ElementScanner6<Void, Void> {
	protected static ProcessingEnvironment prcEnv;
	protected static Types typeUtils;
	protected static Elements elementUtils;

	/** 処理対象。*/
	protected Element classElement;
	/**
	 * 初期設定。
	 * @param pEnv
	 */
	public static void setup(ProcessingEnvironment pEnv) {
		prcEnv = pEnv;
		typeUtils = pEnv.getTypeUtils();
		elementUtils = pEnv.getElementUtils();
	}
	/**
	 * コンストラクタ。
	 * @param element クラスエレメント
	 * @param sqliteHelperTemplate
	 */
	public ScannerBase(Element element) {
		classElement = element;
	}

	/**
	 * 処理対象Elementクラスを取得する。
	 * @return 処理対象Element
	 */
	public Element getClassElement() {
		return classElement;
	}

	/**
	 * テンプレートクラス生成。
	 * @return 各スキャナ用テンプレートクラス
	 */
	protected abstract TemplateBase getTemplate();

	/**
	 * ソース生成処理。
	 */
	public abstract void generate();

	/**
	 * ソースコード出力。
	 * @return
	 * @throws IOException
	 */
	public String output() throws IOException {
		TemplateBase template = getTemplate();
		// mvelからソースコード生成
		String gen = (String) TemplateRuntime.eval(
				ScannerBase.class.getClassLoader().getResourceAsStream(template.getTemplateName()),
				null,
				template.getTemplateArg());
		// ソースコード生成
		String sourcePath = template.getSourcePackageName().concat(".").concat(template.getSourceName());
		JavaFileObject javaFileObj = prcEnv.getFiler().createSourceFile(sourcePath, classElement);
		PrintWriter writer = new PrintWriter(new OutputStreamWriter(javaFileObj.openOutputStream(), "UTF-8"));
		writer.write(gen);
		writer.flush();
		writer.close();
		return gen;
	}

    /**
     * キャメル記法を_記法に変換します。
     *
     * @param s  テキスト
     * @return 結果の文字列
     */
    protected String decamelize(final String s) {
        if (s == null) {
            return null;
        }
        if (s.length() == 1) {
            return s.toUpperCase();
        }
        StringBuilder buf = new StringBuilder(40);
        int pos = 0;
        for (int i = 1; i < s.length(); ++i) {
            if (Character.isUpperCase(s.charAt(i))) {
                if (buf.length() != 0) {
                    buf.append('_');
                }
                buf.append(s.substring(pos, i).toUpperCase());
                pos = i;
            }
        }
        if (buf.length() != 0) {
            buf.append('_');
        }
        buf.append(s.substring(pos, s.length()).toUpperCase());
        return buf.toString();
    }

    /**
     * Mvelテンプレートクラス。
     * @author SPEEDY
     */
    protected abstract class TemplateBase {
    	/** Mvelテンプレートパラメータ。*/
    	protected Map<String, Object> templateArg = new LinkedHashMap<String, Object>();
    	/** 生成クラス名。*/
    	private String sourceName;
    	/** 生成クラスパッケージ名。*/
    	private String sourcePackageName;
    	/**
    	 * Mvel用テンプレートファイル名取得処理。
    	 * @return Mvel用テンプレートファイル名
    	 */
		public abstract String getTemplateName();
    	public Map<String, Object> getTemplateArg() {
    		return templateArg;
    	}
    	public void putTemplateArg(String key, Object value) {
    		templateArg.put(key, value);
    	}
    	public Object getTemplateArg(String key) {
    		return templateArg.get(key);
    	}
    	public String getSourcePackageName() {
			return sourcePackageName;
		}
    	public void setSourcePackageName(String sourcePackageName) {
			this.sourcePackageName = sourcePackageName;
		}
		public String getSourceName() {
			return sourceName;
		}
		public void setSourceName(String sourceName) {
			this.sourceName = sourceName;
		}
    }
}


text:
import {Layout, applyFillContent, isLayoutSizeFixed} from '#core/dom/layout';
import {propagateAttributes} from '#core/dom/propagate-attributes';
import {realChildNodes} from '#core/dom/query';
import {setStyle} from '#core/dom/style';
import {tryPlay} from '#core/dom/video';

import {triggerAnalyticsEvent} from '#utils/analytics';
import {listen} from '#utils/event-helper';
import {dev} from '#utils/log';

import {
  EMPTY_METADATA,
  parseFavicon,
  parseOgImage,
  parseSchemaImage,
  setMediaSession,
  validateMediaMetadata,
} from '../../../src/mediasession-helper';
import {getMode} from '../../../src/mode';
import {assertHttpsUrl} from '../../../src/url';
import {setIsMediaComponent} from '../../../src/video-interface';

const TAG = 'amp-audio';

/**
 * Visible for testing only.
 */
export class AmpAudio extends AMP.BaseElement {
  /** @param {!AmpElement} element */
  constructor(element) {
    super(element);

    /** @private {?Element} */
    this.audio_ = null;

    /** @private {!../../../src/mediasession-helper.MetadataDef} */
    this.metadata_ = EMPTY_METADATA;

    /** @public {boolean} */
    this.isPlaying = false;
  }

  /** @override */
  isLayoutSupported(layout) {
    return isLayoutSizeFixed(layout);
  }

  /** @override */
  buildCallback() {
    // If layout="nodisplay" force autoplay to off
    const layout = this.getLayout();
    if (layout === Layout.NODISPLAY) {
      this.element.removeAttribute('autoplay');
      this.buildAudioElement();
    }

    setIsMediaComponent(this.element);

    this.registerAction('play', this.play_.bind(this));
    this.registerAction('pause', this.pause_.bind(this));
  }

  /** @override */
  mutatedAttributesCallback(mutations) {
    if (!this.audio_) {
      return;
    }

    const src = mutations['src'];
    const controlsList = mutations['controlsList'];
    const loop = mutations['loop'];

    if (src !== undefined || controlsList !== undefined || loop !== undefined) {
      if (src !== undefined) {
        assertHttpsUrl(src, this.element);
      }
      propagateAttributes(
        ['src', 'loop', 'controlsList'],
        this.element,
        this.audio_
      );
    }

    const artist = mutations['artist'];
    const title = mutations['title'];
    const album = mutations['album'];
    const artwork = mutations['artwork'];

    if (
      artist !== undefined ||
      title !== undefined ||
      album !== undefined ||
      artwork !== undefined
    ) {
      this.updateMetadata_();
    }
  }

  /**
   * Builds the internal <audio> element.
   */
  buildAudioElement() {
    const audio = this.element.ownerDocument.createElement('audio');
    if (!audio.play) {
      this.toggleFallback(true);
      return;
    }

    // Force controls otherwise there is no player UI.
    audio.controls = true;

    // TODO(https://go.amp.dev/issue/36303): We explicitly set width 100% to workaround
    // an issue where `<audio>` does not fill the parent container on iOS
    // (https://go.amp.dev/issue/36292).
    // This is required since global styles for `.i-amphtml-fill-content` set width to 0 in
    // order to address a separate bug. Re-assess whether that workaround is needed, and
    // remove this style if so.
    setStyle(audio, 'width', '100%');

    const src = this.getElementAttribute_('src');
    if (src) {
      assertHttpsUrl(src, this.element);
    }
    propagateAttributes(
      [
        'src',
        'preload',
        'autoplay',
        'muted',
        'loop',
        'aria-label',
        'aria-describedby',
        'aria-labelledby',
        'controlsList',
      ],
      this.element,
      audio
    );

    applyFillContent(audio);
    realChildNodes(this.element).forEach((child) => {
      if (child.getAttribute && child.getAttribute('src')) {
        assertHttpsUrl(child.getAttribute('src'), dev().assertElement(child));
      }
      audio.appendChild(child);
    });
    this.element.appendChild(audio);
    this.audio_ = audio;

    listen(this.audio_, 'playing', () => this.audioPlaying_());

    listen(this.audio_, 'play', () =>
      triggerAnalyticsEvent(this.element, 'audio-play')
    );
    listen(this.audio_, 'pause', () =>
      triggerAnalyticsEvent(this.element, 'audio-pause')
    );
  }

  /** @override */
  layoutCallback() {
    const layout = this.getLayout();
    if (layout !== Layout.NODISPLAY) {
      this.buildAudioElement();
    }
    this.updateMetadata_();

    // Resolve layoutCallback right away if the audio won't preload.
    if (this.element.getAttribute('preload') === 'none') {
      return this.audio_;
    }

    return this.loadPromise(this.audio_);
  }

  /** @private */
  updateMetadata_() {
    // Gather metadata
    const {document} = this.getAmpDoc().win;
    const artist = this.getElementAttribute_('artist') || '';
    const title =
      this.getElementAttribute_('title') ||
      this.getElementAttribute_('aria-label') ||
      document.title ||
      '';
    const album = this.getElementAttribute_('album') || '';
    const artwork =
      this.getElementAttribute_('artwork') ||
      parseSchemaImage(document) ||
      parseOgImage(document) ||
      parseFavicon(document) ||
      '';
    this.metadata_ = {
      title,
      artist,
      album,
      artwork: [{src: artwork}],
    };
  }

  /** @override */
  renderOutsideViewport() {
    return true;
  }

  /**
   * Returns the value of the attribute specified
   * @param {string} attr
   * @return {string}
   */
  getElementAttribute_(attr) {
    return this.element.getAttribute(attr);
  }

  /** @override */
  pauseCallback() {
    if (this.audio_) {
      this.audio_.pause();
      this.setPlayingStateForTesting_(false);
    }
  }

  /**
   * Checks if the function is allowed to be called
   * @return {boolean}
   */
  isInvocationValid_() {
    // Don't execute actions if too early, or if the audio element was removed.
    return !!this.audio_;
  }

  /**
   * Pause action for <amp-audio>.
   */
  pause_() {
    if (!this.isInvocationValid_()) {
      return;
    }
    this.audio_.pause();
    this.setPlayingStateForTesting_(false);
  }

  /**
   * Play action for <amp-audio>.
   */
  play_() {
    if (!this.isInvocationValid_()) {
      return;
    }
    tryPlay(this.audio_);
    this.setPlayingStateForTesting_(true);
  }

  /**
   * Sets whether the audio is playing or not.
   * @param {boolean} isPlaying
   * @private
   */
  setPlayingStateForTesting_(isPlaying) {
    if (getMode().test) {
      this.isPlaying = isPlaying;
    }
  }

  /** @private */
  audioPlaying_() {
    const playHandler = () => {
      tryPlay(this.audio_);
      this.setPlayingStateForTesting_(true);
    };
    const pauseHandler = () => {
      this.audio_.pause();
      this.setPlayingStateForTesting_(false);
    };

    // Update the media session
    validateMediaMetadata(this.element, this.metadata_);
    setMediaSession(this.win, this.metadata_, playHandler, pauseHandler);
  }
}

AMP.extension(TAG, '0.1', (AMP) => {
  AMP.registerElement(TAG, AmpAudio);
});


text:
#include <stdlib.h>
#include <string.h>

#include <libelf.h>
#include <gelf.h>
/* Note:
 * Even though we know the Vita is a 32-bit platform and we specifically check
 * that we're operating on a 32-bit ELF only, we still use the GElf family of
 * functions.  This is because they have extra sanity checking baked in.
 */

#ifndef MAP_ANONYMOUS
#  define MAP_ANONYMOUS MAP_ANON
#endif

#ifndef __MINGW32__
/* This may cause trouble with Windows portability, but there are Windows alternatives
 * to mmap() that we can explore later.  It'll probably work under Cygwin.
 */
#include <sys/mman.h>
#else
#define mmap(ptr,size,c,d,e,f) malloc(size)
#define munmap(ptr, size) free(ptr)
#endif

#include "vita-elf.h"
#include "vita-import.h"
#include "elf-defs.h"
#include "fail-utils.h"
#include "endian-utils.h"

static void free_rela_table(vita_elf_rela_table_t *rtable);

static int load_stubs(Elf_Scn *scn, int *num_stubs, vita_elf_stub_t **stubs)
{
	GElf_Shdr shdr;
	Elf_Data *data;
	uint32_t *stub_data;
	int chunk_offset, total_bytes;
	vita_elf_stub_t *curstub;

	gelf_getshdr(scn, &shdr);

	*num_stubs = shdr.sh_size / 16;
	*stubs = calloc(*num_stubs, sizeof(vita_elf_stub_t));

	curstub = *stubs;
	data = NULL; total_bytes = 0;
	while (total_bytes < shdr.sh_size &&
			(data = elf_getdata(scn, data)) != NULL) {

		for (stub_data = (uint32_t *)data->d_buf, chunk_offset = 0;
				chunk_offset < data->d_size;
				stub_data += 4, chunk_offset += 16) {
			curstub->addr = shdr.sh_addr + data->d_off + chunk_offset;
			curstub->library_nid = le32toh(stub_data[0]);
			curstub->module_nid = le32toh(stub_data[1]);
			curstub->target_nid = le32toh(stub_data[2]);
			curstub++;
		}

		total_bytes += data->d_size;
	}

	return 1;
}

static int load_symbols(vita_elf_t *ve, Elf_Scn *scn)
{
	GElf_Shdr shdr;
	Elf_Data *data;
	GElf_Sym sym;
	int total_bytes;
	int data_beginsym, symndx;
	vita_elf_symbol_t *cursym;

	if (elf_ndxscn(scn) == ve->symtab_ndx)
		return 1; /* Already loaded */

	if (ve->symtab != NULL)
		FAILX("ELF file appears to have multiple symbol tables!");

	gelf_getshdr(scn, &shdr);

	ve->num_symbols = shdr.sh_size / shdr.sh_entsize;
	ve->symtab = calloc(ve->num_symbols, sizeof(vita_elf_symbol_t));
	ve->symtab_ndx = elf_ndxscn(scn);

	data = NULL; total_bytes = 0;
	while (total_bytes < shdr.sh_size &&
			(data = elf_getdata(scn, data)) != NULL) {

		data_beginsym = data->d_off / shdr.sh_entsize;
		for (symndx = 0; symndx < data->d_size / shdr.sh_entsize; symndx++) {
			if (gelf_getsym(data, symndx, &sym) != &sym)
				FAILE("gelf_getsym() failed");

			cursym = ve->symtab + symndx + data_beginsym;

			cursym->name = elf_strptr(ve->elf, shdr.sh_link, sym.st_name);
			cursym->value = sym.st_value;
			cursym->type = GELF_ST_TYPE(sym.st_info);
			cursym->binding = GELF_ST_BIND(sym.st_info);
			cursym->shndx = sym.st_shndx;
		}

		total_bytes += data->d_size;
	}

	return 1;
failure:
	return 0;
}

#define THUMB_SHUFFLE(x) ((((x) & 0xFFFF0000) >> 16) | (((x) & 0xFFFF) << 16))
static uint32_t decode_rel_target(uint32_t data, int type, uint32_t addr)
{
	uint32_t upper, lower, sign, j1, j2, imm10, imm11;
	switch(type) {
		case R_ARM_NONE:
		case R_ARM_V4BX:
			return 0xdeadbeef;
		case R_ARM_ABS32:
		case R_ARM_TARGET1:
			return data;
		case R_ARM_REL32:
		case R_ARM_TARGET2:
			return data + addr;
		case R_ARM_PREL31:
			return data + addr;
		case R_ARM_THM_CALL: // bl (THUMB)
			data = THUMB_SHUFFLE(data);
			upper = data >> 16;
			lower = data & 0xFFFF;
			sign = (upper >> 10) & 1;
			j1 = (lower >> 13) & 1;
			j2 = (lower >> 11) & 1;
			imm10 = upper & 0x3ff;
			imm11 = lower & 0x7ff;
			return addr + (((imm11 | (imm10 << 11) | (!(j2 ^ sign) << 21) | (!(j1 ^ sign) << 22) | (sign << 23)) << 1) | (sign ? 0xff000000 : 0));
		case R_ARM_CALL: // bl/blx
		case R_ARM_JUMP24: // b/bl<cond>
			data = (data & 0x00ffffff) << 2;
			// if we got a negative value, sign extend it
			if (data & (1 << 25))
				data |= 0xfc000000;
			return data + addr;
		case R_ARM_MOVW_ABS_NC: //movw
			return ((data & 0xf0000) >> 4) | (data & 0xfff);
		case R_ARM_MOVT_ABS: //movt
			return (((data & 0xf0000) >> 4) | (data & 0xfff)) << 16;
		case R_ARM_THM_MOVW_ABS_NC: //MOVW (THUMB)
			data = THUMB_SHUFFLE(data);
			return (((data >> 16) & 0xf) << 12)
				| (((data >> 26) & 0x1) << 11)
				| (((data >> 12) & 0x7) << 8)
				| (data & 0xff);
		case R_ARM_THM_MOVT_ABS: //MOVT (THUMB)
			data = THUMB_SHUFFLE(data);
			return (((data >> 16) & 0xf) << 28)
				| (((data >> 26) & 0x1) << 27)
				| (((data >> 12) & 0x7) << 24)
				| ((data & 0xff) << 16);
	}

	errx(EXIT_FAILURE, "Invalid relocation type: %d", type);
}

#define REL_HANDLE_NORMAL 0
#define REL_HANDLE_IGNORE -1
#define REL_HANDLE_INVALID -2
static int get_rel_handling(int type)
{
	switch(type) {
		case R_ARM_NONE:
		case R_ARM_V4BX:
			return REL_HANDLE_IGNORE;
		case R_ARM_ABS32:
		case R_ARM_TARGET1:
		case R_ARM_REL32:
		case R_ARM_TARGET2:
		case R_ARM_PREL31:
		case R_ARM_THM_CALL:
		case R_ARM_CALL:
		case R_ARM_JUMP24:
		case R_ARM_MOVW_ABS_NC:
		case R_ARM_MOVT_ABS:
		case R_ARM_THM_MOVW_ABS_NC:
		case R_ARM_THM_MOVT_ABS:
			return REL_HANDLE_NORMAL;
	}

	return REL_HANDLE_INVALID;
}

static int load_rel_table(vita_elf_t *ve, Elf_Scn *scn)
{
	Elf_Scn *text_scn;
	GElf_Shdr shdr, text_shdr;
	Elf_Data *data, *text_data;
	GElf_Rel rel;
	int relndx;

	int rel_sym;
	int handling;

	vita_elf_rela_table_t *rtable = NULL;
	vita_elf_rela_t *currela = NULL;
	uint32_t insn, target = 0;

	gelf_getshdr(scn, &shdr);

	if (!load_symbols(ve, elf_getscn(ve->elf, shdr.sh_link)))
		goto failure;

	rtable = calloc(1, sizeof(vita_elf_rela_table_t));
	ASSERT(rtable != NULL);
	rtable->num_relas = shdr.sh_size / shdr.sh_entsize;
	rtable->relas = calloc(rtable->num_relas, sizeof(vita_elf_rela_t));
	ASSERT(rtable->relas != NULL);

	rtable->target_ndx = shdr.sh_info;
	text_scn = elf_getscn(ve->elf, shdr.sh_info);
	gelf_getshdr(text_scn, &text_shdr);
	text_data = elf_getdata(text_scn, NULL);

	/* We're blatantly assuming here that both of these sections will store
	 * the entirety of their data in one Elf_Data item.  This seems to be true
	 * so far in my testing, and from the libelf source it looks like it's
	 * unlikely to allocate multiple data items on initial file read, but
	 * should be fixed someday. */
	data = elf_getdata(scn, NULL);
	for (relndx = 0; relndx < data->d_size / shdr.sh_entsize; relndx++) {
		if (gelf_getrel(data, relndx, &rel) != &rel)
			FAILX("gelf_getrel() failed");

		currela = rtable->relas + relndx;
		currela->type = GELF_R_TYPE(rel.r_info);
		/* R_ARM_THM_JUMP24 is functionally the same as R_ARM_THM_CALL, however Vita only supports the second one */
		if (currela->type == R_ARM_THM_JUMP24)
			currela->type = R_ARM_THM_CALL;
		/* This one comes from libstdc++.
		 * Should be safe to ignore because it's pc-relative and already encoded in the file. */
		if (currela->type == R_ARM_THM_PC11)
			continue;
		currela->offset = rel.r_offset;

		/* Use memcpy for unaligned relocation. */
		memcpy(&insn, text_data->d_buf+(rel.r_offset - text_shdr.sh_addr), sizeof(insn));
		insn = le32toh(insn);

		handling = get_rel_handling(currela->type);

		if (handling == REL_HANDLE_IGNORE)
			continue;
		else if (handling == REL_HANDLE_INVALID)
			FAILX("Invalid relocation type %d!", currela->type);

		rel_sym = GELF_R_SYM(rel.r_info);
		if (rel_sym >= ve->num_symbols)
			FAILX("REL entry tried to access symbol %d, but only %d symbols loaded", rel_sym, ve->num_symbols);

		currela->symbol = ve->symtab + rel_sym;

		target = decode_rel_target(insn, currela->type, rel.r_offset);

		/* From some testing the added for MOVT/MOVW should actually always be 0 */
		if (currela->type == R_ARM_MOVT_ABS || currela->type == R_ARM_THM_MOVT_ABS)
			currela->addend = target - (currela->symbol->value & 0xFFFF0000);
		else if (currela->type == R_ARM_MOVW_ABS_NC || currela->type == R_ARM_THM_MOVW_ABS_NC)
			currela->addend = target - (currela->symbol->value & 0xFFFF);
		/* Symbol value could be OR'ed with 1 if the function is compiled in Thumb mode,
		 * however for the relocation addend we need the actual address. */
		else if (currela->type == R_ARM_THM_CALL)
			currela->addend = target - (currela->symbol->value & 0xFFFFFFFE);
		else
			currela->addend = target - currela->symbol->value;
	}

	rtable->next = ve->rela_tables;
	ve->rela_tables = rtable;

	return 1;
failure:
	free_rela_table(rtable);
	return 0;
}

static int load_rela_table(vita_elf_t *ve, Elf_Scn *scn)
{
	warnx("RELA sections currently unsupported");
	return 0;
}

static int lookup_stub_symbols(vita_elf_t *ve, int num_stubs, vita_elf_stub_t *stubs, int stubs_ndx, int sym_type)
{
	int symndx;
	vita_elf_symbol_t *cursym;
	int stub;

	for (symndx = 0; symndx < ve->num_symbols; symndx++) {
		cursym = ve->symtab + symndx;

		if (cursym->binding != STB_GLOBAL)
			continue;
		if (cursym->type != STT_FUNC && cursym->type != STT_OBJECT)
			continue;
		if (cursym->shndx != stubs_ndx)
			continue;

		if (cursym->type != sym_type)
			FAILX("Global symbol %s in section %d expected to have type %s; instead has type %s",
					cursym->name, stubs_ndx, elf_decode_st_type(sym_type), elf_decode_st_type(cursym->type));

		for (stub = 0; stub < num_stubs; stub++) {
			if (stubs[stub].addr != cursym->value)
				continue;
			if (stubs[stub].symbol != NULL)
				FAILX("Stub at %06x in section %d has duplicate symbols: %s, %s",
						cursym->value, stubs_ndx, stubs[stub].symbol->name, cursym->name);
			stubs[stub].symbol = cursym;
			break;
		}

		if (stub == num_stubs)
			FAILX("Global symbol %s in section %d not pointing to a valid stub",
					cursym->name, cursym->shndx);
	}

	return 1;

failure:
	return 0;
}

static int is_valid_relsection(vita_elf_t *ve, GElf_Shdr *rel) {
	Elf_Scn *info;
	size_t phnum;
	GElf_Shdr shdr;
	GElf_Phdr phdr;

	ASSERT(rel->sh_type == SHT_REL || rel->sh_type == SHT_RELA);
	ELF_ASSERT(info = elf_getscn(ve->elf, rel->sh_info));
	ELF_ASSERT(gelf_getshdr(info, &shdr));
	ELF_ASSERT(elf_getphdrnum(ve->elf, &phnum) == 0);

	if (shdr.sh_type == SHT_NOBITS) {
		shdr.sh_size = 0;
	}

	// Here we assume that every section falls into EXACTLY one segment
	// However, the ELF format allows for weird things like one section that
	// is partially in one segment and partially in another one (or even
	// multiple).
	// TODO: For robustness, consider these corner cases
	// Right now, we just assume if you have one of these messed up ELFs,
	// we don't support it because it's likely to break in other parts of this
	// code :)
	for (int i = 0; i < phnum; i++) {
		ELF_ASSERT(gelf_getphdr(ve->elf, i, &phdr));
		if (phdr.p_type != PT_LOAD) {
			continue;
		}
		// TODO: Take account of possible integer wrap-arounds
		if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset + shdr.sh_size <= phdr.p_offset + phdr.p_filesz) {
			return 1;
		}
	}

failure:
	return 0;
}

vita_elf_t *vita_elf_load(const char *filename)
{
	vita_elf_t *ve = NULL;
	GElf_Ehdr ehdr;
	Elf_Scn *scn;
	GElf_Shdr shdr;
	size_t shstrndx;
	char *name;
	const char **debug_name;

	GElf_Phdr phdr;
	size_t segment_count, segndx, loaded_segments;
	vita_elf_segment_info_t *curseg;

	if (elf_version(EV_CURRENT) == EV_NONE)
		FAILX("ELF library initialization failed: %s", elf_errmsg(-1));

	ve = calloc(1, sizeof(vita_elf_t));
	ASSERT(ve != NULL);

	if ((ve->file = fopen(filename, "rb")) == NULL)
		FAIL("open %s failed", filename);

	ELF_ASSERT(ve->elf = elf_begin(fileno(ve->file), ELF_C_READ, NULL));

	if (elf_kind(ve->elf) != ELF_K_ELF)
		FAILX("%s is not an ELF file", filename);

	ELF_ASSERT(gelf_getehdr(ve->elf, &ehdr));

	if (ehdr.e_machine != EM_ARM)
		FAILX("%s is not an ARM binary", filename);

	if (ehdr.e_ident[EI_CLASS] != ELFCLASS32 || ehdr.e_ident[EI_DATA] != ELFDATA2LSB)
		FAILX("%s is not a 32-bit, little-endian binary", filename);

	ELF_ASSERT(elf_getshdrstrndx(ve->elf, &shstrndx) == 0);

	scn = NULL;

	while ((scn = elf_nextscn(ve->elf, scn)) != NULL) {
		ELF_ASSERT(gelf_getshdr(scn, &shdr));

		ELF_ASSERT(name = elf_strptr(ve->elf, shstrndx, shdr.sh_name));

		if (shdr.sh_type == SHT_PROGBITS && strcmp(name, ".vitalink.fstubs") == 0) {
			if (ve->fstubs_ndx != 0)
				FAILX("Multiple .vitalink.fstubs sections in binary");
			ve->fstubs_ndx = elf_ndxscn(scn);
			if (!load_stubs(scn, &ve->num_fstubs, &ve->fstubs))
				goto failure;
		} else if (shdr.sh_type == SHT_PROGBITS && strcmp(name, ".vitalink.vstubs") == 0) {
			if (ve->vstubs_ndx != 0)
				FAILX("Multiple .vitalink.vstubs sections in binary");
			ve->vstubs_ndx = elf_ndxscn(scn);
			if (!load_stubs(scn, &ve->num_vstubs, &ve->vstubs))
				goto failure;
		}

		if (shdr.sh_type == SHT_SYMTAB) {
			if (!load_symbols(ve, scn))
				goto failure;
		} else if (shdr.sh_type == SHT_REL) {
			if (!is_valid_relsection(ve, &shdr))
				continue;
			if (!load_rel_table(ve, scn))
				goto failure;
		} else if (shdr.sh_type == SHT_RELA) {
			if (!is_valid_relsection(ve, &shdr))
				continue;
			if (!load_rela_table(ve, scn))
				goto failure;
		}
	}

	if (ve->fstubs_ndx == 0 && ve->vstubs_ndx == 0)
		FAILX("No .vitalink stub sections in binary, probably not a Vita binary");

	if (ve->symtab == NULL)
		FAILX("No symbol table in binary, perhaps stripped out");

	if (ve->rela_tables == NULL)
		FAILX("No relocation sections in binary; use -Wl,-q while compiling");

	if (ve->fstubs_ndx != 0) {
		if (!lookup_stub_symbols(ve, ve->num_fstubs, ve->fstubs, ve->fstubs_ndx, STT_FUNC)) goto failure;
	}

	if (ve->vstubs_ndx != 0) {
		if (!lookup_stub_symbols(ve, ve->num_vstubs, ve->vstubs, ve->vstubs_ndx, STT_OBJECT)) goto failure;
	}

	ELF_ASSERT(elf_getphdrnum(ve->elf, &segment_count) == 0);

	ve->segments = calloc(segment_count, sizeof(vita_elf_segment_info_t));
	ASSERT(ve->segments != NULL);
	loaded_segments = 0;

	for (segndx = 0; segndx < segment_count; segndx++) {
		ELF_ASSERT(gelf_getphdr(ve->elf, segndx, &phdr));

		if (phdr.p_type != PT_LOAD) {
			continue; // skip non-loadable segments
		}

		curseg = ve->segments + loaded_segments;
		curseg->type = phdr.p_type;
		curseg->vaddr = phdr.p_vaddr;
		curseg->memsz = phdr.p_memsz;

		if (curseg->memsz) {
			curseg->vaddr_top = mmap(NULL, curseg->memsz, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
			if (curseg->vaddr_top == NULL)
				FAIL("Could not allocate address space for segment %d", (int)segndx);
			curseg->vaddr_bottom = curseg->vaddr_top + curseg->memsz;
		}

		loaded_segments++;
	}
	ve->num_segments = loaded_segments;

	return ve;

failure:
	if (ve != NULL)
		vita_elf_free(ve);
	return NULL;
}

static void free_rela_table(vita_elf_rela_table_t *rtable)
{
	if (rtable == NULL) return;
	free(rtable->relas);
	free_rela_table(rtable->next);
	free(rtable);
}

void vita_elf_free(vita_elf_t *ve)
{
	int i;

	for (i = 0; i < ve->num_segments; i++) {
		if (ve->segments[i].vaddr_top != NULL)
			munmap((void *)ve->segments[i].vaddr_top, ve->segments[i].memsz);
	}

	/* free() is safe to call on NULL */
	free(ve->fstubs);
	free(ve->vstubs);
	free(ve->symtab);
	if (ve->elf != NULL)
		elf_end(ve->elf);
	if (ve->file != NULL)
		fclose(ve->file);
	free(ve);
}

typedef vita_imports_stub_t *(*find_stub_func_ptr)(vita_imports_module_t *, uint32_t);
static int lookup_stubs(vita_elf_stub_t *stubs, int num_stubs, vita_imports_t **imports, int imports_count, find_stub_func_ptr find_stub, const char *stub_type_name)
{
	int found_all = 1;
	int i, j;
	vita_elf_stub_t *stub;

	for (i = 0; i < num_stubs; i++) {
		stub = &(stubs[i]);

		for (j = 0; j < imports_count; j++) {
			stub->library = vita_imports_find_lib(imports[j], stub->library_nid);
			if (stub->library != NULL) {
				break;
			}
		}

		if (stub->library == NULL) {
			warnx("Unable to find library with NID %u for %s symbol %s",
					stub->library_nid, stub_type_name,
					stub->symbol ? stub->symbol->name : "(unreferenced stub)");
			found_all = 0;
			continue;
		}

		stub->module = vita_imports_find_module(stub->library, stub->module_nid);
		if (stub->module == NULL) {
			warnx("Unable to find module with NID %u for %s symbol %s",
					stub->module_nid, stub_type_name,
					stub->symbol ? stub->symbol->name : "(unreferenced stub)");
			found_all = 0;
			continue;
		}

		stub->target = find_stub(stub->module, stub->target_nid);
		if (stub->target == NULL) {
			warnx("Unable to find %s with NID %u for symbol %s",
					stub_type_name, stub->module_nid,
					stub->symbol ? stub->symbol->name : "(unreferenced stub)");
			found_all = 0;
		}
	}

	return found_all;
}

int vita_elf_lookup_imports(vita_elf_t *ve, vita_imports_t **imports, int imports_count)
{
	int found_all = 1;

	if (!lookup_stubs(ve->fstubs, ve->num_fstubs, imports, imports_count, &vita_imports_find_function, "function"))
		found_all = 0;
	if (!lookup_stubs(ve->vstubs, ve->num_vstubs, imports, imports_count, &vita_imports_find_variable, "variable"))
		found_all = 0;

	return found_all;
}

const void *vita_elf_vaddr_to_host(const vita_elf_t *ve, Elf32_Addr vaddr)
{
	vita_elf_segment_info_t *seg;
	int i;

	for (i = 0, seg = ve->segments; i < ve->num_segments; i++, seg++) {
		if (vaddr >= seg->vaddr && vaddr < seg->vaddr + seg->memsz)
			return seg->vaddr_top + vaddr - seg->vaddr;
	}

	return NULL;
}
const void *vita_elf_segoffset_to_host(const vita_elf_t *ve, int segndx, uint32_t offset)
{
	vita_elf_segment_info_t *seg = ve->segments + segndx;

	if (offset < seg->memsz)
		return seg->vaddr_top + offset;

	return NULL;
}

Elf32_Addr vita_elf_host_to_vaddr(const vita_elf_t *ve, const void *host_addr)
{
	vita_elf_segment_info_t *seg;
	int i;

	if (host_addr == NULL)
		return 0;

	for (i = 0, seg = ve->segments; i < ve->num_segments; i++, seg++) {
		if (host_addr >= seg->vaddr_top && host_addr < seg->vaddr_bottom)
			return seg->vaddr + (uint32_t)(host_addr - seg->vaddr_top);
	}

	return 0;
}

int vita_elf_host_to_segndx(const vita_elf_t *ve, const void *host_addr)
{
	vita_elf_segment_info_t *seg;
	int i;

	for (i = 0, seg = ve->segments; i < ve->num_segments; i++, seg++) {
		if (host_addr >= seg->vaddr_top && host_addr < seg->vaddr_bottom)
			return i;
	}

	return -1;
}

int32_t vita_elf_host_to_segoffset(const vita_elf_t *ve, const void *host_addr, int segndx)
{
	vita_elf_segment_info_t *seg = ve->segments + segndx;

	if (host_addr == NULL)
		return 0;

	if (host_addr >= seg->vaddr_top && host_addr < seg->vaddr_bottom)
		return (uint32_t)(host_addr - seg->vaddr_top);

	return -1;
}

int vita_elf_vaddr_to_segndx(const vita_elf_t *ve, Elf32_Addr vaddr)
{
	vita_elf_segment_info_t *seg;
	int i;

	for (i = 0, seg = ve->segments; i < ve->num_segments; i++, seg++) {
		/* Segments of type EXIDX will duplicate '.ARM.extab .ARM.exidx' sections already present in the data segment
		 * Since these won't be loaded, we should prefer the actual data segment */
		if (seg->type == SHT_ARM_EXIDX)
			continue;
		if (vaddr >= seg->vaddr && vaddr < seg->vaddr + seg->memsz)
			return i;
	}

	return -1;
}

/* vita_elf_vaddr_to_segoffset won't check the validity of the address, it may have been fuzzy-matched */
uint32_t vita_elf_vaddr_to_segoffset(const vita_elf_t *ve, Elf32_Addr vaddr, int segndx)
{
	vita_elf_segment_info_t *seg = ve->segments + segndx;

	if (vaddr == 0)
		return 0;

	return vaddr - seg->vaddr;
}


text: - [ ] Better documentation and examples