text:
#pragma once

#include "CodeBlock.h"
#include "Interpreter.h"

namespace JSC {

template<typename Block, typename Functor, typename Instruction>
void computeUsesForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instruction* instruction, const Functor& functor)
{
    if (opcodeID != op_enter && codeBlock->wasCompiledWithDebuggingOpcodes() && codeBlock->scopeRegister().isValid())
        functor(codeBlock, instruction, opcodeID, codeBlock->scopeRegister().offset());

    switch (opcodeID) {
    // No uses.
    case op_new_regexp:
    case op_new_array_buffer:
    case op_throw_static_error:
    case op_debug:
    case op_jneq_ptr:
    case op_loop_hint:
    case op_jmp:
    case op_new_object:
    case op_enter:
    case op_argument_count:
    case op_catch:
    case op_profile_control_flow:
    case op_create_direct_arguments:
    case op_create_cloned_arguments:
    case op_get_rest_length:
    case op_check_traps:
    case op_get_argument:
        return;
    case op_assert:
    case op_get_scope:
    case op_to_this:
    case op_check_tdz:
    case op_profile_type:
    case op_throw:
    case op_end:
    case op_ret:
    case op_jtrue:
    case op_jfalse:
    case op_jeq_null:
    case op_jneq_null:
    case op_dec:
    case op_inc:
    case op_log_shadow_chicken_prologue: {
        ASSERT(opcodeLengths[opcodeID] > 1);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        return;
    }
    case op_jlesseq:
    case op_jgreater:
    case op_jgreatereq:
    case op_jnless:
    case op_jnlesseq:
    case op_jngreater:
    case op_jngreatereq:
    case op_jless:
    case op_set_function_name:
    case op_log_shadow_chicken_tail: {
        ASSERT(opcodeLengths[opcodeID] > 2);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        return;
    }
    case op_put_by_val_direct:
    case op_put_by_val: {
        ASSERT(opcodeLengths[opcodeID] > 3);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        return;
    }
    case op_put_by_index:
    case op_put_by_id:
    case op_put_to_scope:
    case op_put_to_arguments: {
        ASSERT(opcodeLengths[opcodeID] > 3);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        return;
    }
    case op_put_by_id_with_this: {
        ASSERT(opcodeLengths[opcodeID] > 4);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        return;
    }
    case op_put_by_val_with_this: {
        ASSERT(opcodeLengths[opcodeID] > 4);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        return;
    }
    case op_put_getter_by_id:
    case op_put_setter_by_id: {
        ASSERT(opcodeLengths[opcodeID] > 4);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        return;
    }
    case op_put_getter_setter_by_id: {
        ASSERT(opcodeLengths[opcodeID] > 5);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
        return;
    }
    case op_put_getter_by_val:
    case op_put_setter_by_val: {
        ASSERT(opcodeLengths[opcodeID] > 4);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        return;
    }
    case op_define_data_property: {
        ASSERT(opcodeLengths[opcodeID] > 4);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        return;
    }
    case op_define_accessor_property: {
        ASSERT(opcodeLengths[opcodeID] > 5);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
        return;
    }
    case op_spread:
    case op_get_property_enumerator:
    case op_get_enumerable_length:
    case op_new_func_exp:
    case op_new_generator_func_exp:
    case op_new_async_func_exp:
    case op_to_index_string:
    case op_create_lexical_environment:
    case op_resolve_scope:
    case op_get_from_scope:
    case op_to_primitive:
    case op_try_get_by_id:
    case op_get_by_id:
    case op_get_by_id_proto_load:
    case op_get_by_id_unset:
    case op_get_array_length:
    case op_typeof:
    case op_is_empty:
    case op_is_undefined:
    case op_is_boolean:
    case op_is_number:
    case op_is_object:
    case op_is_object_or_null:
    case op_is_cell_with_type:
    case op_is_function:
    case op_to_number:
    case op_to_string:
    case op_negate:
    case op_neq_null:
    case op_eq_null:
    case op_not:
    case op_mov:
    case op_new_array_with_size:
    case op_create_this:
    case op_del_by_id:
    case op_unsigned:
    case op_new_func:
    case op_new_generator_func:
    case op_new_async_func:
    case op_get_parent_scope:
    case op_create_scoped_arguments:
    case op_create_rest:
    case op_get_from_arguments: {
        ASSERT(opcodeLengths[opcodeID] > 2);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        return;
    }
    case op_has_generic_property:
    case op_has_indexed_property:
    case op_enumerator_structure_pname:
    case op_enumerator_generic_pname:
    case op_get_by_val:
    case op_in:
    case op_overrides_has_instance:
    case op_instanceof:
    case op_add:
    case op_mul:
    case op_div:
    case op_mod:
    case op_sub:
    case op_pow:
    case op_lshift:
    case op_rshift:
    case op_urshift:
    case op_bitand:
    case op_bitxor:
    case op_bitor:
    case op_less:
    case op_lesseq:
    case op_greater:
    case op_greatereq:
    case op_nstricteq:
    case op_stricteq:
    case op_neq:
    case op_eq:
    case op_push_with_scope:
    case op_get_by_id_with_this:
    case op_del_by_val:
    case op_tail_call_forward_arguments: {
        ASSERT(opcodeLengths[opcodeID] > 3);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        return;
    }
    case op_get_by_val_with_this: {
        ASSERT(opcodeLengths[opcodeID] > 4);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        return;
    }
    case op_instanceof_custom:
    case op_has_structure_property:
    case op_construct_varargs:
    case op_call_varargs:
    case op_tail_call_varargs: {
        ASSERT(opcodeLengths[opcodeID] > 4);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        return;
    }
    case op_get_direct_pname: {
        ASSERT(opcodeLengths[opcodeID] > 5);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
        return;
    }
    case op_switch_string:
    case op_switch_char:
    case op_switch_imm: {
        ASSERT(opcodeLengths[opcodeID] > 3);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        return;
    }
    case op_new_array_with_spread:
    case op_new_array:
    case op_strcat: {
        int base = instruction[2].u.operand;
        int count = instruction[3].u.operand;
        for (int i = 0; i < count; i++)
            functor(codeBlock, instruction, opcodeID, base - i);
        return;
    }
    case op_construct:
    case op_call_eval:
    case op_call:
    case op_tail_call: {
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        int argCount = instruction[3].u.operand;
        int registerOffset = -instruction[4].u.operand;
        int lastArg = registerOffset + CallFrame::thisArgumentOffset();
        for (int i = 0; i < argCount; i++)
            functor(codeBlock, instruction, opcodeID, lastArg + i);
        if (opcodeID == op_call_eval)
            functor(codeBlock, instruction, opcodeID, codeBlock->scopeRegister().offset());
        return;
    }
    case op_yield: {
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
        return;
    }
    default:
        RELEASE_ASSERT_NOT_REACHED();
        break;
    }
}

template<typename Block, typename Instruction, typename Functor>
void computeDefsForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instruction* instruction, const Functor& functor)
{
    switch (opcodeID) {
    // These don't define anything.
    case op_put_to_scope:
    case op_end:
    case op_throw:
    case op_throw_static_error:
    case op_assert:
    case op_debug:
    case op_ret:
    case op_jmp:
    case op_jtrue:
    case op_jfalse:
    case op_jeq_null:
    case op_jneq_null:
    case op_jneq_ptr:
    case op_jless:
    case op_jlesseq:
    case op_jgreater:
    case op_jgreatereq:
    case op_jnless:
    case op_jnlesseq:
    case op_jngreater:
    case op_jngreatereq:
    case op_loop_hint:
    case op_switch_imm:
    case op_switch_char:
    case op_switch_string:
    case op_put_by_id:
    case op_put_by_id_with_this:
    case op_put_by_val_with_this:
    case op_put_getter_by_id:
    case op_put_setter_by_id:
    case op_put_getter_setter_by_id:
    case op_put_getter_by_val:
    case op_put_setter_by_val:
    case op_put_by_val:
    case op_put_by_val_direct:
    case op_put_by_index:
    case op_define_data_property:
    case op_define_accessor_property:
    case op_profile_type:
    case op_profile_control_flow:
    case op_put_to_arguments:
    case op_set_function_name:
    case op_check_traps:
    case op_log_shadow_chicken_prologue:
    case op_log_shadow_chicken_tail:
    case op_yield:
#define LLINT_HELPER_OPCODES(opcode, length) case opcode:
        FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);
#undef LLINT_HELPER_OPCODES
        return;
    // These all have a single destination for the first argument.
    case op_argument_count:
    case op_to_index_string:
    case op_get_enumerable_length:
    case op_has_indexed_property:
    case op_has_structure_property:
    case op_has_generic_property:
    case op_get_direct_pname:
    case op_get_property_enumerator:
    case op_enumerator_structure_pname:
    case op_enumerator_generic_pname:
    case op_get_parent_scope:
    case op_push_with_scope:
    case op_create_lexical_environment:
    case op_resolve_scope:
    case op_strcat:
    case op_to_primitive:
    case op_create_this:
    case op_new_array:
    case op_new_array_with_spread:
    case op_spread:
    case op_new_array_buffer:
    case op_new_array_with_size:
    case op_new_regexp:
    case op_new_func:
    case op_new_func_exp:
    case op_new_generator_func:
    case op_new_generator_func_exp:
    case op_new_async_func:
    case op_new_async_func_exp:
    case op_call_varargs:
    case op_tail_call_varargs:
    case op_tail_call_forward_arguments:
    case op_construct_varargs:
    case op_get_from_scope:
    case op_call:
    case op_tail_call:
    case op_call_eval:
    case op_construct:
    case op_try_get_by_id:
    case op_get_by_id:
    case op_get_by_id_proto_load:
    case op_get_by_id_unset:
    case op_get_by_id_with_this:
    case op_get_by_val_with_this:
    case op_get_array_length:
    case op_overrides_has_instance:
    case op_instanceof:
    case op_instanceof_custom:
    case op_get_by_val:
    case op_typeof:
    case op_is_empty:
    case op_is_undefined:
    case op_is_boolean:
    case op_is_number:
    case op_is_object:
    case op_is_object_or_null:
    case op_is_cell_with_type:
    case op_is_function:
    case op_in:
    case op_to_number:
    case op_to_string:
    case op_negate:
    case op_add:
    case op_mul:
    case op_div:
    case op_mod:
    case op_sub:
    case op_pow:
    case op_lshift:
    case op_rshift:
    case op_urshift:
    case op_bitand:
    case op_bitxor:
    case op_bitor:
    case op_inc:
    case op_dec:
    case op_eq:
    case op_neq:
    case op_stricteq:
    case op_nstricteq:
    case op_less:
    case op_lesseq:
    case op_greater:
    case op_greatereq:
    case op_neq_null:
    case op_eq_null:
    case op_not:
    case op_mov:
    case op_new_object:
    case op_to_this:
    case op_check_tdz:
    case op_get_scope:
    case op_create_direct_arguments:
    case op_create_scoped_arguments:
    case op_create_cloned_arguments:
    case op_del_by_id:
    case op_del_by_val:
    case op_unsigned:
    case op_get_from_arguments:
    case op_get_argument:
    case op_create_rest:
    case op_get_rest_length: {
        ASSERT(opcodeLengths[opcodeID] > 1);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        return;
    }
    case op_catch: {
        ASSERT(opcodeLengths[opcodeID] > 2);
        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
        return;
    }
    case op_enter: {
        for (unsigned i = codeBlock->m_numVars; i--;)
            functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(i).offset());
        return;
    }
    }
}

} // namespace JSC


text:
class CreateEventNoteRevisions < ActiveRecord::Migration[4.2]
  def change
    create_table :event_note_revisions do |t|
      t.integer :student_id
      t.integer :educator_id
      t.integer :event_note_type_id
      t.text :text
      t.datetime :created_at
      t.datetime :updated_at
      t.integer :event_note_id
      t.integer :version

      t.timestamps
    end
  end
end

redpajama_set_name: RedPajamaGithub


text:
package io.crate.analyze;

import io.crate.analyze.expressions.ExpressionAnalysisContext;
import io.crate.analyze.expressions.ExpressionAnalyzer;
import io.crate.analyze.expressions.SubqueryAnalyzer;
import io.crate.analyze.expressions.ValueNormalizer;
import io.crate.analyze.relations.AbstractTableRelation;
import io.crate.analyze.relations.AnalyzedRelation;
import io.crate.analyze.relations.FullQualifiedNameFieldProvider;
import io.crate.analyze.relations.NameFieldProvider;
import io.crate.analyze.relations.RelationAnalysisContext;
import io.crate.analyze.relations.RelationAnalyzer;
import io.crate.analyze.relations.StatementAnalysisContext;
import io.crate.analyze.relations.select.SelectAnalysis;
import io.crate.analyze.relations.select.SelectAnalyzer;
import io.crate.common.collections.Lists2;
import io.crate.expression.eval.EvaluatingNormalizer;
import io.crate.expression.symbol.Literal;
import io.crate.expression.symbol.Symbol;
import io.crate.metadata.ColumnIdent;
import io.crate.metadata.CoordinatorTxnCtx;
import io.crate.metadata.NodeContext;
import io.crate.metadata.Reference;
import io.crate.metadata.RowGranularity;
import io.crate.metadata.table.Operation;
import io.crate.metadata.table.TableInfo;
import io.crate.sql.tree.Assignment;
import io.crate.sql.tree.AstVisitor;
import io.crate.sql.tree.Expression;
import io.crate.sql.tree.IntegerLiteral;
import io.crate.sql.tree.LongLiteral;
import io.crate.sql.tree.SubscriptExpression;
import io.crate.sql.tree.Update;
import io.crate.types.ArrayType;
import io.crate.types.ObjectType;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.RandomAccess;
import java.util.function.Predicate;

/**
 * Used to analyze statements like: `UPDATE t1 SET col1 = ? WHERE id = ?`
 */
public final class UpdateAnalyzer {

    private static final Predicate<Reference> IS_OBJECT_ARRAY =
        input -> input.valueType().id() == ArrayType.ID
                 && ((ArrayType<?>) input.valueType()).innerType().id() == ObjectType.ID;

    private final NodeContext nodeCtx;
    private final RelationAnalyzer relationAnalyzer;

    UpdateAnalyzer(NodeContext nodeCtx, RelationAnalyzer relationAnalyzer) {
        this.nodeCtx = nodeCtx;
        this.relationAnalyzer = relationAnalyzer;
    }

    public AnalyzedUpdateStatement analyze(Update update, ParamTypeHints typeHints, CoordinatorTxnCtx txnCtx) {
        /* UPDATE t1 SET col1 = ?, col2 = ? WHERE id = ?`
         *               ^^^^^^^^^^^^^^^^^^       ^^^^^^
         *               assignments               whereClause
         *
         *               col1 = ?
         *               |      |
         *               |     source
         *             columnName/target
         */
        StatementAnalysisContext stmtCtx = new StatementAnalysisContext(typeHints, Operation.UPDATE, txnCtx);
        final RelationAnalysisContext relCtx = stmtCtx.startRelation();
        AnalyzedRelation relation = relationAnalyzer.analyze(update.relation(), stmtCtx);
        stmtCtx.endRelation();

        MaybeAliasedStatement maybeAliasedStatement = MaybeAliasedStatement.analyze(relation);
        relation = maybeAliasedStatement.nonAliasedRelation();

        if (!(relation instanceof AbstractTableRelation)) {
            throw new UnsupportedOperationException("UPDATE is only supported on base-tables");
        }
        AbstractTableRelation<?> table = (AbstractTableRelation<?>) relation;
        EvaluatingNormalizer normalizer = new EvaluatingNormalizer(nodeCtx, RowGranularity.CLUSTER, null, table);
        SubqueryAnalyzer subqueryAnalyzer =
            new SubqueryAnalyzer(relationAnalyzer, new StatementAnalysisContext(typeHints, Operation.READ, txnCtx));

        ExpressionAnalyzer sourceExprAnalyzer = new ExpressionAnalyzer(
            txnCtx,
            nodeCtx,
            typeHints,
            new FullQualifiedNameFieldProvider(
                relCtx.sources(),
                relCtx.parentSources(),
                txnCtx.sessionContext().searchPath().currentSchema()
            ),
            subqueryAnalyzer
        );
        ExpressionAnalysisContext exprCtx = new ExpressionAnalysisContext();

        Map<Reference, Symbol> assignmentByTargetCol = getAssignments(
            update.assignments(), typeHints, txnCtx, table, normalizer, subqueryAnalyzer, sourceExprAnalyzer, exprCtx);

        Symbol query = Objects.requireNonNullElse(
            sourceExprAnalyzer.generateQuerySymbol(update.whereClause(), exprCtx),
            Literal.BOOLEAN_TRUE
        );
        query = maybeAliasedStatement.maybeMapFields(query);

        Symbol normalizedQuery = normalizer.normalize(query, txnCtx);
        SelectAnalysis selectAnalysis = SelectAnalyzer.analyzeSelectItems(
            update.returningClause(),
            relCtx.sources(),
            sourceExprAnalyzer,
            exprCtx
        );
        List<Symbol> outputSymbol = Lists2.map(selectAnalysis.outputSymbols(), x -> normalizer.normalize(x, txnCtx));
        return new AnalyzedUpdateStatement(
            table,
            assignmentByTargetCol,
            normalizedQuery,
            outputSymbol.isEmpty() ? null : outputSymbol
        );
    }

    private HashMap<Reference, Symbol> getAssignments(List<Assignment<Expression>> assignments,
                                                      ParamTypeHints typeHints,
                                                      CoordinatorTxnCtx txnCtx,
                                                      AbstractTableRelation<?> table,
                                                      EvaluatingNormalizer normalizer,
                                                      SubqueryAnalyzer subqueryAnalyzer,
                                                      ExpressionAnalyzer sourceExprAnalyzer,
                                                      ExpressionAnalysisContext exprCtx) {
        HashMap<Reference, Symbol> assignmentByTargetCol = new HashMap<>();
        ExpressionAnalyzer targetExprAnalyzer = new ExpressionAnalyzer(
            txnCtx,
            nodeCtx,
            typeHints,
            new NameFieldProvider(table),
            subqueryAnalyzer,
            Operation.UPDATE
        );
        assert assignments instanceof RandomAccess
            : "assignments should implement RandomAccess for indexed loop to avoid iterator allocations";
        TableInfo tableInfo = table.tableInfo();
        for (int i = 0; i < assignments.size(); i++) {
            Assignment<Expression> assignment = assignments.get(i);
            AssignmentNameValidator.ensureNoArrayElementUpdate(assignment.columnName());

            Symbol target = normalizer.normalize(targetExprAnalyzer.convert(assignment.columnName(), exprCtx), txnCtx);
            assert target instanceof Reference : "AstBuilder restricts left side of assignments to Columns/Subscripts";
            Reference targetCol = (Reference) target;
            if (hasMatchingParent(tableInfo, targetCol, IS_OBJECT_ARRAY)) {
                // cannot update fields of object arrays
                throw new IllegalArgumentException("Updating fields of object arrays is not supported");
            }

            Symbol source = ValueNormalizer.normalizeInputForReference(
                normalizer.normalize(sourceExprAnalyzer.convert(assignment.expression(), exprCtx), txnCtx),
                targetCol,
                tableInfo,
                s -> normalizer.normalize(s, txnCtx)
            );
            if (assignmentByTargetCol.put(targetCol, source) != null) {
                throw new IllegalArgumentException("Target expression repeated: " + targetCol.column().sqlFqn());
            }
        }
        return assignmentByTargetCol;
    }

    private static boolean hasMatchingParent(TableInfo tableInfo, Reference info, Predicate<Reference> parentMatchPredicate) {
        ColumnIdent parent = info.column().getParent();
        while (parent != null) {
            Reference parentInfo = tableInfo.getReference(parent);
            if (parentMatchPredicate.test(parentInfo)) {
                return true;
            }
            parent = parent.getParent();
        }
        return false;
    }

    private static class AssignmentNameValidator extends AstVisitor<Void, Boolean> {

        private static final AssignmentNameValidator INSTANCE = new AssignmentNameValidator();

        static void ensureNoArrayElementUpdate(Expression expression) {
            expression.accept(INSTANCE, false);
        }

        @Override
        protected Void visitSubscriptExpression(SubscriptExpression node, Boolean childOfSubscript) {
            node.index().accept(this, true);
            return super.visitSubscriptExpression(node, childOfSubscript);
        }

        private Void validateLiteral(Boolean childOfSubscript) {
            if (childOfSubscript) {
                throw new IllegalArgumentException("Updating a single element of an array is not supported");
            }
            return null;
        }

        @Override
        protected Void visitLongLiteral(LongLiteral node, Boolean childOfSubscript) {
            return validateLiteral(childOfSubscript);
        }

        @Override
        protected Void visitIntegerLiteral(IntegerLiteral node, Boolean childOfSubscript) {
            return validateLiteral(childOfSubscript);
        }
    }
}


text:
layout: page
title: About
group: navigation
---

I'm a data scientist based in London, UK. My CV can be found here.

I want to use this blog as a vehicle for my own personal learning more than anything, but would be very pleased if it proved in any way useful to anyone else.

Of course  I am on most to every social media platform going, so please connect with me and share.

Get in touch,

twitter

linkedin

github

email

Views expressd on this website are mine alone and do not reflect the views of my employer.


text:
<!DOCTYPE html>

    <meta charset="UTF-8">
    <title>RoslynPad</title>
    <meta property="og:image" content="https://i.imgur.com/ixnekTd.png" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="stylesheets/normalize.css" media="screen">
    <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
    <link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen">

            RoslynPad

A simple C# editor based on Roslyn and AvalonEdit

        View on GitHub
        Download v15.1
        Download Source

        <video width="720" height="540" controls
               poster="https://res.cloudinary.com/aelij/video/upload/v1489299110/roslynpad-jsondemo_gmxcxr.jpg">
            <source src="https://res.cloudinary.com/aelij/video/upload/s--V-3jPJgs--/f_auto/v1489299110/roslynpad-jsondemo_gmxcxr.mp4" type="video/mp4">
        </video>

            RoslynPad is maintained by aelij.

            This page was generated by GitHub Pages using the Cayman theme by Jason Long.


text:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.thalmic.android.sample.glass"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="19" />

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name="com.thalmic.android.sample.glass.MainActivity"
            android:icon="@drawable/ic_glass_logo"
            android:immersive="true"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>

            <meta-data
                android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/voice_trigger" />
        </activity>

        <service android:name="com.thalmic.android.sample.glass.MyoGlassService" />

        <activity
            android:name="com.thalmic.myo.scanner.ScanActivity"
            android:label="@string/myosdk__title_activity_scan"
            android:theme="@style/myosdk__ScanActivityTheme" />
    </application>

</manifest>


text:
namespace blink {

class Element;
class IntersectionObserver;

class IntersectionObservation final
    : public GarbageCollected<IntersectionObservation> {
 public:
  IntersectionObservation(IntersectionObserver&,
                          Element&,
                          bool shouldReportRootBounds);

  struct IntersectionGeometry {
    LayoutRect targetRect;
    LayoutRect intersectionRect;
    LayoutRect rootRect;
    bool doesIntersect;

    IntersectionGeometry() : doesIntersect(false) {}
  };

  IntersectionObserver& observer() const { return *m_observer; }
  Element* target() const { return m_target; }
  unsigned lastThresholdIndex() const { return m_lastThresholdIndex; }
  void setLastThresholdIndex(unsigned index) { m_lastThresholdIndex = index; }
  bool shouldReportRootBounds() const { return m_shouldReportRootBounds; }
  void computeIntersectionObservations(DOMHighResTimeStamp);
  void disconnect();
  void clearRootAndRemoveFromTarget();

  DECLARE_TRACE();

 private:
  void applyRootMargin(LayoutRect&) const;
  void initializeGeometry(IntersectionGeometry&) const;
  void initializeTargetRect(LayoutRect&) const;
  void initializeRootRect(LayoutRect&) const;
  void clipToRoot(IntersectionGeometry&) const;
  void mapTargetRectToTargetFrameCoordinates(LayoutRect&) const;
  void mapRootRectToRootFrameCoordinates(LayoutRect&) const;
  void mapRootRectToTargetFrameCoordinates(LayoutRect&) const;
  bool computeGeometry(IntersectionGeometry&) const;

  Member<IntersectionObserver> m_observer;

  WeakMember<Element> m_target;

  unsigned m_shouldReportRootBounds : 1;
  unsigned m_lastThresholdIndex : 30;
};

}  // namespace blink

#endif  // IntersectionObservation_h


text:
/* macntcp.c -- macintosh nifty application library async TCP routines
 */
/* (C) Copyright 1995 by Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * and its documentation for any purpose is hereby granted without
 * fee, provided that the above copyright notice appear in all copies
 * and that both that copyright notice and this permission notice
 * appear in supporting documentation, and that the name of Carnegie
 * Mellon University not be used in advertising or publicity
 * pertaining to distribution of the software without specific,
 * written prior permission.  Carnegie Mellon University makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied
 * warranty.
 *
 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
/* (C) Copyright 1994-1995 by Christopher J. Newman
 * All Rights Reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Christopher J. Newman not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Christopher J. Newman makes no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
 * SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 * OF THIS SOFTWARE.
 *
 * Author:	Christopher J. Newman
 * Message:	This is a nifty program.
 */

#include <string.h>
#include <MacTCPCommonTypes.h>
#include <TCPPB.h>
#include <AddressXlation.h>
#include <GetMyIPAddr.h>
#include "macnapp.h"

#define DEF_STREAM_SIZE 8192
#define MAX_TCPCON  16
#define RDS			8

/* write buffer for TCP writes
 */
typedef struct tcpwb {
	short rused;			/* number of RDS used (-1 == in TCPsend) */
	short wused;			/* amount of small buffer used */
	rdsEntry rds[RDS+1];	/* array of RDS pointers */
	char fflag[RDS+1];		/* free flags for RDS pointers (1 = call DisposPtr) */
	char *buf;				/* write buffer */
} tcpwb;

/* structure describing a TCP connection
 */
typedef struct tcpinfo {
	short state;			/* current state */
	short rclose;			/* remote host wants to close */
	short lclose;			/* local host wants to close */
	int havedata:1;			/* data is available to read */
	int urgent:1;			/* TCP in urgent mode */
	int push:1;				/* next write should be pushed */
	int pushed:1;			/* last write was pushed */
	int reading:1;			/* reading data */
	int server:1;			/* is a server, rather than client */
	int gethost:1;			/* getting hostname -- not a real connection */
	int dnrdone:1;			/* DNR query is done */
	short wbnum;			/* write buffer for next write */
	unsigned short wbsize;	/* size of write buffer */
	unsigned short reason;	/* reason for TCP termination */
	StreamPtr stream;		/* TCP stream */
	ip_port port;			/* TCP port number to connect to */
	void *context;			/* user context */
	na_tcpreadp *callback;	/* callback function */
	rdsEntry rrds[RDS+1];	/* read RDS structure */
	tcpwb wb[2];			/* write buffers */
	struct hostInfo host;	/* hostname & ip_addr of host */
	TCPiopb pb;				/* parameter block for TCP connect/write/close */
	TCPiopb rpb;			/* parameter block for TCP read */
	char buf[1];			/* stream buffer follows */
} tcpinfo;

/* TCP task state information
 */
struct tcpstate {
	na_win win;
	short tcp_driver;
	na_tcpinitp *tcp_initp;
	tcpinfo *tcpbufs[MAX_TCPCON];
	IOParam *open_pb;
	long waiticks, waitstart;
	short waitpercent;
	long streamsize;
	byte TOS, precedence;
	unsigned short wbsize;
	char localhost[256];
} **tcpstate = NULL;
#define tstate ((struct tcpstate *) win)

/* tcp state bitmasks */
#define TCP_PBINUSE   0x04		/* tcp->pb in use */
#define TCP_DNSINUSE  0x08		/* DNS in use */
#define TCP_NOTREADY  0x10      /* not ready for reading */
/* tcp states */
#define TCP_READY     1									/* inactive */
#define TCP_RESOLVE   (TCP_NOTREADY + TCP_DNSINUSE + 0)	/* resolving hostname */
#define TCP_GETHOST   (TCP_NOTREADY + TCP_DNSINUSE + 1)	/* looking up hostname */
#define TCP_WRITING   (TCP_PBINUSE + 0)					/* writing data */
#define TCP_CONNECT   (TCP_NOTREADY + TCP_PBINUSE + 0)	/* waiting for a connection */
#define TCP_CLOSING   (TCP_NOTREADY + TCP_PBINUSE + 1)	/* waiting for TCPclose */
#define TCP_CLOSED    2									/* closed */

/* free write buffer storage
 */
static void freewb(tcpwb *wb)
{
	short i;

	for (i = 0; wb->rds[i].length; ++i) {
		if (wb->fflag[i]) {
			DisposPtr(wb->rds[i].ptr);
			wb->fflag[i] = 0;
		}
	}
	wb->rused = 0;
	wb->wused = 0;
}

/* make sure tcp_driver is open
 */
static short tcp_checkdriver()
{
	short msg = NATCP_nodriver;
	struct tcpstate *ts = *tcpstate;
	IOParam *opb = ts->open_pb;

	if (!opb) return (1);
	if (opb->ioResult == 1) return (0);
	if (opb->ioResult == noErr && OpenResolver(nil) == noErr) {
		ts->tcp_driver = opb->ioRefNum;
		msg = NATCP_connect;
	}
	DisposPtr((Ptr) opb);
	ts = *tcpstate;
	ts->open_pb = NULL;
	(*ts->tcp_initp)(msg);

	return (1);
}

/* wait for MacTCP to finish whatever it's doing, with user cancel
 */
static short tcp_wait(struct tcpstate *ts, tcpinfo *tcp)
{
	KeyMap mapkeys;
#define keys ((unsigned char *)mapkeys)
	short percent;

	while (!tcp_checkdriver()
		|| (tcp && (tcp->state & TCP_DNSINUSE) && ! (volatile) tcp->dnrdone)
		|| (tcp && (tcp->state & TCP_PBINUSE) && (volatile short) tcp->pb.ioResult == 1)) {
		if (ts) {
			if (!ts->waiticks) return (0);
			percent = ((TickCount() - ts->waitstart) * 100) / ts->waiticks;
			if (percent > 100) percent = 100;
			if (percent != ts->waitpercent) {
				(*ts->tcp_initp)(ts->waitpercent = percent);
			}
			if (percent == 100) return (0);
		}
		SystemTask();
		GetKeys(mapkeys);
		if ((keys[0x37 >> 3] >> (0x37 & 7))
			& (keys[0x2f >> 3] >> (0x2f & 7)) & 1) {
			return (0);
		}
	}

	return (1);
}

/* clean up the TCP task
 */
static short tcp_closep(na_win *win)
{
	short i, j;
	tcpinfo *tcp;
	tcpwb *wb;
	TCPiopb pb;

	tstate->waitstart = TickCount();
	tstate->waitpercent = 0;
	tcp_wait(tstate, NULL);
	memset((void *) &pb, 0, sizeof (pb));
	for (i = 0; i < MAX_TCPCON; ++i) {
		if ((tcp = tstate->tcpbufs[i]) != NULL) {
			/* wait for MacTCP to finish what it's doing, but permit user cancel */
			if (!tcp->server || tcp->state != TCP_CONNECT) tcp_wait(tstate, tcp);
			if (!tcp->gethost) {
				pb.ioCRefNum = tstate->tcp_driver;
				pb.tcpStream = tcp->stream;
				pb.csCode = TCPRelease;
				PBControl((ParmBlkPtr) &pb, false);
			}
			freewb(tcp->wb);
			freewb(tcp->wb + 1);
			DisposPtr((Ptr) tcp);
			tstate->tcpbufs[i] = NULL;
		}
	}
	tcpstate = NULL;
	if (tstate->tcp_driver) CloseResolver();

	return (NA_CLOSED);
}

/* begin writing data
 */
static short beginwrite(tcpinfo *tcp)
{
	tcpwb *wb = tcp->wb + tcp->wbnum;

	/* if connection terminated, or we've sent a TCPclose, we can't write */
	if (tcp->rclose == 3 || tcp->lclose > 1) return (0);
	memset((void *) &tcp->pb.csParam, 0, sizeof (tcp->pb.csParam));
	tcp->pb.csCode = TCPSend;
	tcp->pb.csParam.send.ulpTimeoutValue = 60; /* 1 minute to send data */
	tcp->pb.csParam.send.ulpTimeoutAction = 0;
	tcp->pb.csParam.send.validityFlags = 0xC0;
	tcp->pb.csParam.send.wdsPtr = (Ptr) wb->rds;
	tcp->pb.csParam.send.pushFlag = tcp->pushed = tcp->push;
	PBControl((ParmBlkPtr) &tcp->pb, true);
	tcp->push = 0;
	tcp->wbnum = 1 - tcp->wbnum;
	wb->rused = -1;

	return (tcp->state = TCP_WRITING);
}

/* do I/O polling
 */
short NATCPtask(na_win *win)
{
	tcpinfo *tcp;
	rdsEntry *rds, *trds;
	short result, newstate;
	short processed = NA_PROCESSED;
	na_tcp i;
	tcpwb *wb;
	int j;

	/* finish off driver initialization: */
	if (!tstate->tcp_driver) {
		if (!tcp_checkdriver()) return (NA_NOTPROCESSED);
		if (!tstate->tcp_driver) return (NA_REQCLOSE);
	}
	/* loop through connections */
	for (i = 0; i < MAX_TCPCON; ++i) {
		if ((tcp = tstate->tcpbufs[i]) != NULL) do {
			/* read data if we have it */
			if (!tcp->reading && !tcp->rclose && tcp->havedata && tcp->state != TCP_CONNECT) {
				tcp->rpb.ioCRefNum = tstate->tcp_driver;
				tcp->rpb.tcpStream = tcp->stream;
				tcp->rpb.csCode = TCPNoCopyRcv;
				tcp->rpb.csParam.receive.rdsPtr = (Ptr) tcp->rrds;
				tcp->rpb.csParam.receive.commandTimeoutValue = 5;
				tcp->rpb.csParam.receive.rdsLength = RDS;
				if (tcp->pushed) {
					tcp->rpb.csParam.receive.commandTimeoutValue = 1;
					tcp->rpb.csParam.receive.rdsLength = 1;
				}
				tcp->havedata = 0;
				PBControl((ParmBlkPtr) &tcp->rpb, tcp->pushed ? false : true);
				tcp->reading = 1;
				tcp->pushed = 0;
			}
			if (tcp->reading) {
				if ((result = tcp->rpb.ioResult) == 1) {
					processed = NA_NOTPROCESSED;
				} else {
					tcp->reading = 0;
					if (result != noErr) {
						if (result != commandTimeout) {
							(*tcp->callback)(tcp->context, i, NATCP_noread, result, NULL);
						}
					} else {
						result = NATCP_data | NATCP_more;
						if (tcp->rpb.csParam.receive.urgentFlag) tcp->urgent = 1;
						if (tcp->urgent) result |= NATCP_urgent;
						if (tcp->rpb.csParam.receive.markFlag) tcp->urgent = 0;
						for (rds = tcp->rrds; rds->length; ++rds) {
							if (!rds[1].length) result &= ~NATCP_more;
							(*tcp->callback)(tcp->context, i, result,
								rds->length, rds->ptr);
						}
						tcp->rpb.csCode = TCPRcvBfrReturn;
						PBControl((ParmBlkPtr) &tcp->rpb, false);
					}
				}
			}
			result = tcp->pb.ioResult;
			newstate = 0;
			switch (tcp->state) {
				case TCP_GETHOST:
					if (tcp->dnrdone) {
						tcp->rclose = 3;
						newstate = TCP_CLOSED;
						if (tcp->host.rtnCode != noErr) {
							(*tcp->callback)(tcp->context, i, NATCP_nohost,
								tcp->host.rtnCode, NULL);
						} else {
							(*tcp->callback)(tcp->context, i, NATCP_connect,
								strlen(tcp->host.cname), tcp->host.cname);
							strcpy(tstate->localhost, tcp->host.cname);
						}
					}
					break;
				case TCP_RESOLVE:
					if (tcp->dnrdone) {
						if (tcp->host.rtnCode != noErr) {
							tcp->rclose = 3;
							newstate = TCP_CLOSED;
							(*tcp->callback)(tcp->context, i, NATCP_nohost,
								tcp->host.rtnCode, NULL);
						} else if (!tcp->lclose) {
							memset((void *) &tcp->pb, 0, sizeof (tcp->pb));
							tcp->pb.ioCRefNum = tstate->tcp_driver;
							tcp->pb.tcpStream = tcp->stream;
							tcp->pb.csParam.open.ulpTimeoutValue = 30;
							tcp->pb.csParam.open.ulpTimeoutAction = 1; /* Abort on timeout */
							tcp->pb.csParam.open.tosFlags = tstate->TOS;
							tcp->pb.csParam.open.precedence = tstate->precedence;
							tcp->pb.csParam.open.validityFlags =
								timeoutValue|timeoutAction|typeOfService|precedence;
							tcp->pb.csParam.open.remoteHost = tcp->host.addr[0];
							if (tcp->server) {
								tcp->pb.csCode = TCPPassiveOpen;
								tcp->pb.csParam.open.commandTimeoutValue = 0;
								tcp->pb.csParam.open.remotePort = 0;
								tcp->pb.csParam.open.localPort = tcp->port;
							} else {
								tcp->pb.csCode = TCPActiveOpen;
								tcp->pb.csParam.open.remotePort = tcp->port;
								tcp->pb.csParam.open.localPort = 0;
							}
							PBControl((ParmBlkPtr) &tcp->pb, true);
							newstate = TCP_CONNECT;
						}
					}
					break;
				case TCP_CONNECT:
					if (result == 1) {
						processed = NA_NOTPROCESSED;
						break;
					}
					if (result != noErr) {
						tcp->rclose = 3;
						newstate = TCP_CLOSED;
						(*tcp->callback)(tcp->context, i, NATCP_nocon, result, NULL);
					} else {
						newstate = TCP_READY;
						if (tcp->server) {
							tcp->port = tcp->pb.csParam.open.remotePort;
							if (!*tcp->host.cname) {
								AddrToStr(tcp->pb.csParam.open.remoteHost, tcp->host.cname);
							}
						}
						(*tcp->callback)(tcp->context, i, NATCP_connect,
							tcp->port, tcp->host.cname);
					}
					break;
				case TCP_READY:
					/* Write data if we have it */
					wb = tcp->wb + tcp->wbnum;
					if (wb->rused && (newstate = beginwrite(tcp))) {
						break;
					}
					/* check if other side wants to close */
					if (tcp->rclose == 1) {
						tcp->rclose = 2;
						(*tcp->callback)(tcp->context, i, NATCP_closing, 0, NULL);
					}
					/* check if connection needs closing at this end */
	 				if (tcp->lclose == 1) {
						tcp->lclose = 2;
						tcp->pb.csCode = TCPClose;
						tcp->pb.csParam.close.validityFlags = 0xC0;
						tcp->pb.csParam.close.ulpTimeoutValue = 30; /* give 30 secs to close */
						tcp->pb.csParam.close.ulpTimeoutAction = 0;
						PBControl((ParmBlkPtr) &tcp->pb, true);
						newstate = TCP_CLOSING;
						break;
					}
					/* check if connection closed at both ends */
					if (tcp->rclose == 3) {
						(*tcp->callback)(tcp->context, i, NATCP_closed, tcp->reason, NULL);
						newstate = TCP_CLOSED;
					}
					break;
				case TCP_WRITING:
					if (result == 1) {
						processed = NA_NOTPROCESSED;
						break;
					}
					wb = tcp->wb;
					if (wb->rused != -1) ++wb;
					freewb(wb);
					if (result != noErr) {
						tcp->pushed = 0;
						(*tcp->callback)(tcp->context, i, NATCP_nowrite, result, NULL);
					}
					newstate = TCP_READY;
					break;
				case TCP_CLOSING:
					if (result == 1) {
						processed = NA_NOTPROCESSED;
						break;
					}
					newstate = TCP_READY;
					break;
				case TCP_CLOSED:
					if (!tcp->rclose) break;
					if (!tcp->gethost) {
						tcp->pb.csCode = TCPRelease;
						PBControl((ParmBlkPtr)&tcp->pb, false);
					}
					freewb(tcp->wb);
					freewb(tcp->wb + 1);
					DisposPtr((Ptr) tcp);
					tstate->tcpbufs[i] = NULL;
					break;
			}
			if (newstate) tcp->state = newstate;
		} while (newstate);
	}

	return (processed);
}

/* Async notification routine
 */
static pascal void myTCPNotifyProc(StreamPtr stream, unsigned short eventCode,
	Ptr userDataPtr, unsigned short terminReason, struct ICMPReport *icmpMsg)
{
	tcpinfo *tcp = (tcpinfo *) userDataPtr;

	switch (eventCode) {
		case TCPTerminate:
			tcp->rclose = 3;
			tcp->reason = terminReason;
			break;
		case TCPClosing:
			tcp->rclose = 1;
			break;
		case TCPDataArrival:
			tcp->havedata = 1;
			break;
		case TCPUrgent:
			tcp->urgent = 1;
			break;
	}
}

/* DNR resultproc */
static pascal void addrproc(struct hostInfo *hinfop, char *udata)
{
	((tcpinfo *) udata)->dnrdone = 1;
}

/* callback to pass TCP info to window
 */
static void winreadp(void *context, na_tcp i, short status, long len, char *buf)
{
	natcp_win *w;

	w = (natcp_win *) NAlockWindow((na_win **) context);
	w->s = i;
	(*w->readp)(&w->winp, status, len, buf);
	NAunlockWindowh((na_win **) context, &w->winp);
}

/* adjust TCP settings
 */
void NATCPsettings(long streamsize, short type_of_service, short precedence, unsigned short wbsize)
{
	if (!streamsize) streamsize = DEF_STREAM_SIZE;
	(*tcpstate)->streamsize = streamsize ? streamsize : DEF_STREAM_SIZE;
	(*tcpstate)->TOS = type_of_service;
	(*tcpstate)->precedence = precedence;
	if (!wbsize) wbsize = 1024;
	(*tcpstate)->wbsize = wbsize;
}

/* initialize TCP system
 */
void NATCPinit(na_tcpinitp *initp)
{
	IOParam *pb;
	int i;
	struct tcpstate *ts;

	pb = (IOParam *) NewPtrClear(sizeof (IOParam));
	tcpstate = (struct tcpstate **) NAaddtask(NATCPtask, sizeof (struct tcpstate));
	if (!tcpstate || !pb) {
		(*initp)(NATCP_nomem);
	} else {
		pb->ioNamePtr = "\p.IPP";
		PBOpen((ParmBlkPtr) pb, true);
		ts = *tcpstate;
		for (i = 0; i < MAX_TCPCON; ++i) ts->tcpbufs[i] = NULL;
		ts->waiticks = 60; /* wait 1 sec for TCP close by default */
		ts->win.type = NA_TCPTYPE;
		ts->win.closep = tcp_closep;
		ts->win.priority = -1;
		ts->tcp_initp = initp;
		ts->open_pb = pb;
		NATCPsettings(0, 0, 0, 0);
	}
}

/* get a TCP buffer block
 */
static tcpinfo *getTCPbuf(na_tcpreadp *callback, void *context, int *id)
{
	int i;
	tcpinfo *tcp;

	/* make sure driver is open */
	if (!(*tcpstate)->tcp_driver
		&& (!tcp_wait(NULL, NULL) || !(*tcpstate)->tcp_driver)) {
		(*callback)(context, -1, NATCP_nodriver, 0, NULL);
		return (NULL);
	}

	/* find pointer slot and create buffer */
	for (i = 0; i < MAX_TCPCON && (*tcpstate)->tcpbufs[i]; ++i);
	if (i == MAX_TCPCON) {
		(*callback)(context, -1, NATCP_notcpbuf, 0, NULL);
		return (NULL);
	}
	tcp = (tcpinfo *) NewPtr(sizeof (tcpinfo) - 1
		+ (*tcpstate)->streamsize + (unsigned long) (*tcpstate)->wbsize * 2);
	if (!tcp) {
		(*callback)(context, -1, NATCP_nomem, 0, NULL);
		return (NULL);
	};
	*id = i;
	(*tcpstate)->tcpbufs[i] = tcp;
	memset((char *) tcp, 0, sizeof (tcpinfo));

	/* initialize fields from global state */
	tcp->wbsize = (*tcpstate)->wbsize;
	tcp->wb[0].buf = tcp->buf + (*tcpstate)->streamsize;
	tcp->wb[1].buf = tcp->wb[0].buf + tcp->wbsize;
	tcp->pb.ioCRefNum = (*tcpstate)->tcp_driver;
	tcp->context = context;
	tcp->callback = callback;

	return (tcp);
}

/* get host name
 */
void NATCPgethost(na_tcpreadp *callback, void *context)
{
	int id;
	tcpinfo *tcp;
	struct IPParamBlock *ippb;
	na_win *win;

	if ((*tcpstate)->localhost[0]) {
		win = NAlockWindow((na_win **) tcpstate);
		(*callback)(context, -1, NATCP_connect, strlen(tstate->localhost),
			tstate->localhost);
		NAunlockWindowh((na_win **) tcpstate, win);
	} else if ((tcp = getTCPbuf(callback, context, &id)) != NULL) {
		/* here we make the assumption that an IP param block is smaller than
		 * a TCP param block.  This seems like a safe assumption to me.
		 */
		ippb = (struct IPParamBlock *) &tcp->pb;
		/* get IP address */
		ippb->ioCRefNum = (*tcpstate)->tcp_driver;
		ippb->csCode = ipctlGetAddr;
		PBControl((ParmBlkPtr)ippb, false);
		if (ippb->ioResult != 0) {
			(*callback)(context, -1, NATCP_notcpbuf, ippb->ioResult, NULL);
			DisposPtr((Ptr) tcp);
			(*tcpstate)->tcpbufs[id] = NULL;
		} else {
			/* begin IP address lookup */
			tcp->dnrdone = 0;
			AddrToName(ippb->ourAddress, &tcp->host, addrproc, (char *) tcp);
			tcp->state = TCP_GETHOST;
			tcp->gethost = 1;
		}
	}
}

/* open a TCP connection
 */
na_tcp NATCPopen(na_tcpreadp *callback, void *context, char *host, long port, short flags)
{
	int i, err = NATCP_notcpbuf;
	OSErr resolve = noErr;
	tcpinfo *tcp;

	if ((tcp = getTCPbuf(callback, context, &i)) == NULL) return (-1);
	if (flags & NATCP_server) tcp->server = 1;
	tcp->port = port;
	tcp->pb.csCode = TCPCreate;
	tcp->pb.csParam.create.rcvBuff = (Ptr) tcp->buf;
	tcp->pb.csParam.create.rcvBuffLen = (*tcpstate)->streamsize;
	tcp->pb.csParam.create.notifyProc = myTCPNotifyProc;
	tcp->pb.csParam.create.userDataPtr = (Ptr) tcp;
	PBControl((ParmBlkPtr)&tcp->pb, false);
	if (tcp->pb.ioResult == 0) {
		tcp->state = TCP_RESOLVE;
		tcp->stream = tcp->pb.tcpStream;
		/* a server isn't required to have a hostname */
		if (!host && tcp->server) return (i);
		tcp->dnrdone = 0;
		resolve = StrToAddr(host, &tcp->host, addrproc, (char *) tcp);
		if (resolve == noErr) tcp->dnrdone = 1;
		if (resolve == cacheFault || resolve == noErr) {
			return (i);
		}
		err = NATCP_nohost;
	}
	DisposPtr((Ptr) tcp);
	(*tcpstate)->tcpbufs[i] = NULL;
	(*callback)(context, -1, err, resolve, NULL);

	return (-1);
}

/* open a connection to a tcp window
 */
na_tcp NATCPwinopen(natcp_win *w, char *host, long port, short flags)
{
	return (NATCPopen(winreadp, (void *) RecoverHandle((Ptr) w), host, port, flags));
}

/* pass a buffer to tcp connection for writing
 *  dispose of -1 = copy data
 */
short NATCPwrite(na_tcp i, Ptr data, long len, short dispose)
{
	tcpinfo *tcp = (*tcpstate)->tcpbufs[i];
	rdsEntry *rds = NULL;
	tcpwb *wb;
	long totallen = 0;
	int j;

	if (tcp == NULL || tcp->lclose > 0 || tcp->rclose == 3) {
		return (NATCP_nocon);
	}
	wb = tcp->wb + tcp->wbnum;
	if (wb->rused == RDS) wb = tcp->wb + (1 - tcp->wbnum);
	if (wb->rused == -1 || wb->rused == RDS) return (NATCP_notcpbuf);
	for (j = 0; j < wb->rused; ++j) {
		totallen += wb->rds[j].length;
	}
	if (totallen + len >= 65535) return (NATCP_notcpbuf);
	rds = wb->rds + wb->rused;
	rds->length = len;
	rds->ptr = data;
	rds[1].length = 0;
	if (dispose < 0) {
		if (len < tcp->wbsize - wb->wused) {
			/* if data short enough, use small internal buffer */
			rds->ptr = wb->buf + wb->wused;
			wb->wused += len;
			dispose = 0;
			/* If adjacent to last rds, attach to it */
			if (wb->rused && rds[-1].ptr + rds[-1].length == rds->ptr) {
				--wb->rused;
				rds[-1].length += len;
				rds->length = 0;
			}
		} else {
			rds->ptr = NewPtr(len);
			if (!rds->ptr) return (NATCP_nomem);
			dispose = 1;
		}
		memcpy(rds->ptr, data, len);
	}
	wb->fflag[wb->rused++] = dispose;
	if (tcp->push && tcp->state == TCP_READY) {
		(void) beginwrite(tcp);
	}

	return (NATCP_data);
}

/* put a character on the TCP connection -- optimized for fast turnaround
 */
short NATCPputchar(na_tcp i, char c)
{
	(*tcpstate)->tcpbufs[i]->push = 1;

	return (NATCPwrite(i, (Ptr) &c, 1, -1));
}

/* close a TCP connection
 */
void NATCPclose(na_tcp i)
{
	tcpinfo *tcp = (*tcpstate)->tcpbufs[i];

	if (tcp && tcp->lclose < 1) tcp->lclose = 1;
}

/* dispose of all TCP system resources
 */
void NATCPdone(long waiticks)
{
	struct tcpstate *ts;

	if (tcpstate) {
		ts = (struct tcpstate *) NAlockWindow((na_win **) tcpstate);
		ts->waiticks = waiticks;
		NAcloseWindow((na_win *) ts, NA_REQCLOSE);
	}
}


text:
<?php

$factory('Difftechnology\Notifynder\Models\NotificationCategory', [

    'name' => $faker->name,
    'text' => 'test notification',
]);

$factory('Difftechnology\Tests\Models\User', [

    'name' => $faker->name,
    'surname' => $faker->lastName,
]);

$factory('Difftechnology\Notifynder\Models\Notification', [

    'from_id' => 'factory:Difftechnology\Tests\Models\User',
    'from_type' => 'Difftechnology\Tests\Models\User',
    'to_id' => 'factory:Difftechnology\Tests\Models\User',
    'to_type' => 'Difftechnology\Tests\Models\User',
    'category_id' => 'factory:Difftechnology\Notifynder\Models\NotificationCategory',
    'url' => $faker->url,
    'extra' => json_encode(['exta.name' => $faker->name]),
    'read' => 0,
    'expire_time' => null,
    'created_at' => $faker->dateTime,
    'updated_at' => $faker->dateTime,
]);

$factory('Difftechnology\Notifynder\Models\NotificationGroup', [
    'name' => $faker->name,
]);


text:
import toDate from "../toDate/index.js";
import requiredArgs from "../_lib/requiredArgs/index.js";
/**
 * @name getYear
 * @category Year Helpers
 * @summary Get the year of the given date.
 *
 * @description
 * Get the year of the given date.
 *
 * ### v2.0.0 breaking changes:
 *
 * - [Changes that are common for the whole library](https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#Common-Changes).
 *
 * @param {Date|Number} date - the given date
 * @returns {Number} the year
 * @throws {TypeError} 1 argument required
 *
 * @example
 * // Which year is 2 July 2014?
 * const result = getYear(new Date(2014, 6, 2))
 * //=> 2014
 */

export default function getYear(dirtyDate) {
  requiredArgs(1, arguments);
  return toDate(dirtyDate).getFullYear();
}


text:
package org.apache.lucene.store;

import org.apache.lucene.codecs.Codec; // javadocs
import org.apache.lucene.codecs.CodecUtil;
import org.apache.lucene.codecs.LiveDocsFormat; // javadocs
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexFileNames;
import org.apache.lucene.store.DataOutput; // javadocs
import org.apache.lucene.util.IOUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * Class for accessing a compound stream.
 * This class implements a directory, but is limited to only read operations.
 * Directory methods that would normally modify data throw an exception.
 *

 * All files belonging to a segment have the same name with varying extensions.
 * The extensions correspond to the different file formats used by the {@link Codec}.
 * When using the Compound File format these files are collapsed into a
 * single <tt>.cfs</tt> file (except for the {@link LiveDocsFormat}, with a
 * corresponding <tt>.cfe</tt> file indexing its sub-files.
 *

 * Files:
 *

 *
<tt>.cfs</tt>: An optional "virtual" file consisting of all the other
 *    index files for systems that frequently run out of file handles.
 *
<tt>.cfe</tt>: The "virtual" compound file's entry table holding all
 *    entries in the corresponding .cfs file.
 *

 *
Description:

 *

 *
Compound (.cfs) --> Header, FileData FileCount

 *
Compound Entry Table (.cfe) --> Header, FileCount, <FileName,
 *       DataOffset, DataLength> FileCount

 *
Header --> {@link CodecUtil#writeHeader CodecHeader}

 *
FileCount --> {@link DataOutput#writeVInt VInt}

 *
DataOffset,DataLength --> {@link DataOutput#writeLong UInt64}

 *
FileName --> {@link DataOutput#writeString String}

 *
FileData --> raw file data

 *

 *
Notes:

 *

 *
FileCount indicates how many files are contained in this compound file.
 *       The entry table that follows has that many entries.
 *
Each directory entry contains a long pointer to the start of this file's data
 *       section, the files length, and a String with that file's name.
 *

 *
 * @lucene.experimental
 */
public final class CompoundFileDirectory extends Directory {

  /** Offset/Length for a slice inside of a compound file */
  public static final class FileEntry {
    long offset;
    long length;
  }

  private final Directory directory;
  private final String fileName;
  protected final int readBufferSize;
  private final Map<String,FileEntry> entries;
  private final boolean openForWrite;
  private static final Map<String,FileEntry> SENTINEL = Collections.emptyMap();
  private final CompoundFileWriter writer;
  private final IndexInputSlicer handle;

  /**
   * Create a new CompoundFileDirectory.
   */
  public CompoundFileDirectory(Directory directory, String fileName, IOContext context, boolean openForWrite) throws IOException {
    this.directory = directory;
    this.fileName = fileName;
    this.readBufferSize = BufferedIndexInput.bufferSize(context);
    this.isOpen = false;
    this.openForWrite = openForWrite;
    if (!openForWrite) {
      boolean success = false;
      handle = directory.createSlicer(fileName, context);
      try {
        this.entries = readEntries(handle, directory, fileName);
        success = true;
      } finally {
        if (!success) {
          IOUtils.closeWhileHandlingException(handle);
        }
      }
      this.isOpen = true;
      writer = null;
    } else {
      assert !(directory instanceof CompoundFileDirectory) : "compound file inside of compound file: " + fileName;
      this.entries = SENTINEL;
      this.isOpen = true;
      writer = new CompoundFileWriter(directory, fileName);
      handle = null;
    }
  }

  private static final byte CODEC_MAGIC_BYTE1 = (byte) (CodecUtil.CODEC_MAGIC >>> 24);
  private static final byte CODEC_MAGIC_BYTE2 = (byte) (CodecUtil.CODEC_MAGIC >>> 16);
  private static final byte CODEC_MAGIC_BYTE3 = (byte) (CodecUtil.CODEC_MAGIC >>> 8);
  private static final byte CODEC_MAGIC_BYTE4 = (byte) CodecUtil.CODEC_MAGIC;

  /** Helper method that reads CFS entries from an input stream */
  private static final Map<String, FileEntry> readEntries(
      IndexInputSlicer handle, Directory dir, String name) throws IOException {
    IOException priorE = null;
    IndexInput stream = null, entriesStream = null;
    // read the first VInt. If it is negative, it's the version number
    // otherwise it's the count (pre-3.1 indexes)
    try {
      final Map<String,FileEntry> mapping;
      stream = handle.openFullSlice();
      final int firstInt = stream.readVInt();
      // impossible for 3.0 to have 63 files in a .cfs, CFS writer was not visible
      // and separate norms/etc are outside of cfs.
      if (firstInt == CODEC_MAGIC_BYTE1) {
        byte secondByte = stream.readByte();
        byte thirdByte = stream.readByte();
        byte fourthByte = stream.readByte();
        if (secondByte != CODEC_MAGIC_BYTE2 ||
            thirdByte != CODEC_MAGIC_BYTE3 ||
            fourthByte != CODEC_MAGIC_BYTE4) {
          throw new CorruptIndexException("Illegal/impossible header for CFS file: "
                                         + secondByte + "," + thirdByte + "," + fourthByte);
        }
        CodecUtil.checkHeaderNoMagic(stream, CompoundFileWriter.DATA_CODEC,
            CompoundFileWriter.VERSION_START, CompoundFileWriter.VERSION_START);
        final String entriesFileName = IndexFileNames.segmentFileName(
                                              IndexFileNames.stripExtension(name), "",
                                              IndexFileNames.COMPOUND_FILE_ENTRIES_EXTENSION);
        entriesStream = dir.openInput(entriesFileName, IOContext.READONCE);
        CodecUtil.checkHeader(entriesStream, CompoundFileWriter.ENTRY_CODEC, CompoundFileWriter.VERSION_START, CompoundFileWriter.VERSION_START);
        final int numEntries = entriesStream.readVInt();
        mapping = new HashMap<String,FileEntry>(numEntries);
        for (int i = 0; i < numEntries; i++) {
          final FileEntry fileEntry = new FileEntry();
          final String id = entriesStream.readString();
          FileEntry previous = mapping.put(id, fileEntry);
          if (previous != null) {
            throw new CorruptIndexException("Duplicate cfs entry id=" + id + " in CFS: " + entriesStream);
          }
          fileEntry.offset = entriesStream.readLong();
          fileEntry.length = entriesStream.readLong();
        }
      } else {
        // TODO remove once 3.x is not supported anymore
        mapping = readLegacyEntries(stream, firstInt);
      }
      return mapping;
    } catch (IOException ioe) {
      priorE = ioe;
    } finally {
      IOUtils.closeWhileHandlingException(priorE, stream, entriesStream);
    }
    // this is needed until Java 7's real try-with-resources:
    throw new AssertionError("impossible to get here");
  }

  private static Map<String, FileEntry> readLegacyEntries(IndexInput stream,
      int firstInt) throws CorruptIndexException, IOException {
    final Map<String,FileEntry> entries = new HashMap<String,FileEntry>();
    final int count;
    final boolean stripSegmentName;
    if (firstInt < CompoundFileWriter.FORMAT_PRE_VERSION) {
      if (firstInt < CompoundFileWriter.FORMAT_NO_SEGMENT_PREFIX) {
        throw new CorruptIndexException("Incompatible format version: "
            + firstInt + " expected >= " + CompoundFileWriter.FORMAT_NO_SEGMENT_PREFIX + " (resource: " + stream + ")");
      }
      // It's a post-3.1 index, read the count.
      count = stream.readVInt();
      stripSegmentName = false;
    } else {
      count = firstInt;
      stripSegmentName = true;
    }

    // read the directory and init files
    long streamLength = stream.length();
    FileEntry entry = null;
    for (int i=0; i<count; i++) {
      long offset = stream.readLong();
      if (offset < 0 || offset > streamLength) {
        throw new CorruptIndexException("Invalid CFS entry offset: " + offset + " (resource: " + stream + ")");
      }
      String id = stream.readString();

      if (stripSegmentName) {
        // Fix the id to not include the segment names. This is relevant for
        // pre-3.1 indexes.
        id = IndexFileNames.stripSegmentName(id);
      }

      if (entry != null) {
        // set length of the previous entry
        entry.length = offset - entry.offset;
      }

      entry = new FileEntry();
      entry.offset = offset;

      FileEntry previous = entries.put(id, entry);
      if (previous != null) {
        throw new CorruptIndexException("Duplicate cfs entry id=" + id + " in CFS: " + stream);
      }
    }

    // set the length of the final entry
    if (entry != null) {
      entry.length = streamLength - entry.offset;
    }

    return entries;
  }

  public Directory getDirectory() {
    return directory;
  }

  public String getName() {
    return fileName;
  }

  @Override
  public synchronized void close() throws IOException {
    if (!isOpen) {
      // allow double close - usually to be consistent with other closeables
      return; // already closed
     }
    isOpen = false;
    if (writer != null) {
      assert openForWrite;
      writer.close();
    } else {
      IOUtils.close(handle);
    }
  }

  @Override
  public synchronized IndexInput openInput(String name, IOContext context) throws IOException {
    ensureOpen();
    assert !openForWrite;
    final String id = IndexFileNames.stripSegmentName(name);
    final FileEntry entry = entries.get(id);
    if (entry == null) {
      throw new FileNotFoundException("No sub-file with id " + id + " found (fileName=" + name + " files: " + entries.keySet() + ")");
    }
    return handle.openSlice(name, entry.offset, entry.length);
  }

  /** Returns an array of strings, one for each file in the directory. */
  @Override
  public String[] listAll() {
    ensureOpen();
    String[] res;
    if (writer != null) {
      res = writer.listAll();
    } else {
      res = entries.keySet().toArray(new String[entries.size()]);
      // Add the segment name
      String seg = IndexFileNames.parseSegmentName(fileName);
      for (int i = 0; i < res.length; i++) {
        res[i] = seg + res[i];
      }
    }
    return res;
  }

  /** Returns true iff a file with the given name exists. */
  @Override
  public boolean fileExists(String name) {
    ensureOpen();
    if (this.writer != null) {
      return writer.fileExists(name);
    }
    return entries.containsKey(IndexFileNames.stripSegmentName(name));
  }

  /** Not implemented
   * @throws UnsupportedOperationException always: not supported by CFS */
  @Override
  public void deleteFile(String name) {
    throw new UnsupportedOperationException();
  }

  /** Not implemented
   * @throws UnsupportedOperationException always: not supported by CFS */
  public void renameFile(String from, String to) {
    throw new UnsupportedOperationException();
  }

  /** Returns the length of a file in the directory.
   * @throws IOException if the file does not exist */
  @Override
  public long fileLength(String name) throws IOException {
    ensureOpen();
    if (this.writer != null) {
      return writer.fileLength(name);
    }
    FileEntry e = entries.get(IndexFileNames.stripSegmentName(name));
    if (e == null)
      throw new FileNotFoundException(name);
    return e.length;
  }

  @Override
  public IndexOutput createOutput(String name, IOContext context) throws IOException {
    ensureOpen();
    return writer.createOutput(name, context);
  }

  @Override
  public void sync(Collection<String> names) {
    throw new UnsupportedOperationException();
  }

  /** Not implemented
   * @throws UnsupportedOperationException always: not supported by CFS */
  @Override
  public Lock makeLock(String name) {
    throw new UnsupportedOperationException();
  }

  @Override
  public IndexInputSlicer createSlicer(final String name, IOContext context)
      throws IOException {
    ensureOpen();
    assert !openForWrite;
    final String id = IndexFileNames.stripSegmentName(name);
    final FileEntry entry = entries.get(id);
    if (entry == null) {
      throw new FileNotFoundException("No sub-file with id " + id + " found (fileName=" + name + " files: " + entries.keySet() + ")");
    }
    return new IndexInputSlicer() {
      @Override
      public void close() {
      }

      @Override
      public IndexInput openSlice(String sliceDescription, long offset, long length) throws IOException {
        return handle.openSlice(sliceDescription, entry.offset + offset, length);
      }

      @Override
      public IndexInput openFullSlice() throws IOException {
        return openSlice("full-slice", 0, entry.length);
      }
    };
  }

  @Override
  public String toString() {
    return "CompoundFileDirectory(file=\"" + fileName + "\" in dir=" + directory + ")";
  }
}


text:
namespace Gu.Wpf.Reactive
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Windows.Data;
    using Gu.Reactive;

    /// <summary>
    /// Formats condition history as a string for display in tooltip.
    /// </summary>
    [ValueConversion(typeof(ConditionHistoryPoint), typeof(string))]
    public sealed class ConditionHistoryToStringConverter : IValueConverter
    {
        /// <summary> Gets the default instance.</summary>
        public static readonly ConditionHistoryToStringConverter Default = new();

        /// <inheritdoc/>
        public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value switch
            {
                ICondition condition => this.Convert(condition.History, targetType, parameter, culture),
                IEnumerable<ConditionHistoryPoint> xs
                   when SameDay(xs)
                   => string.Join(Environment.NewLine, xs.OrderByDescending(x => x.TimeStamp).Select(x => $"{x.TimeStamp.ToLocalTime().ToString("T", DateTimeFormatInfo.CurrentInfo)} {State(x)}")),
                IEnumerable<ConditionHistoryPoint> xs
                    => string.Join(Environment.NewLine, xs.OrderByDescending(x => x.TimeStamp).Select(x => $"{x.TimeStamp.ToLocalTime().ToString("yyyy-MM-dd HH: mm:ss", DateTimeFormatInfo.CurrentInfo)} {State(x)}")),
                _ => throw new ArgumentException($"Expected {nameof(IEnumerable<ConditionHistoryPoint>)} or {nameof(ICondition)}", nameof(value)),
            };

            bool SameDay(IEnumerable<ConditionHistoryPoint> xs)
            {
                var min = DateTime.MaxValue;
                var max = DateTime.MinValue;
                foreach (var p in xs)
                {
                    if (p.TimeStamp < min)
                    {
                        min = p.TimeStamp;
                    }

                    if (p.TimeStamp > max)
                    {
                        max = p.TimeStamp;
                    }
                }

                return max - min < TimeSpan.FromHours(24);
            }

            string State(ConditionHistoryPoint p) => p.State switch
            {
                true => "true",
                false => "false",
                null => "null",
            };
        }

        /// <inheritdoc/>
        object IValueConverter.ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new System.NotSupportedException($"{nameof(ConditionHistoryToStringConverter)} can only be used in OneWay bindings");
        }
    }
}