text:
%% -*- coding:utf-8 -*-
\section{Одноразовый блокнот}
\rindex{Одноразовый блокнот}
Схема одноразового блокнота была предложена в 1917 году Мэйджором
Дж. Моборном и Г. Вернамом. Классический одноразовый блокнот представляет собой
некоторый набор случайных ключей, каждый из которых равен по размеру
отправляемому сообщению и используется только один раз.

Предположим что мы хотим зашифровать сообщение на некотором языке
(например на английском). Число символов (букв) которое используется в
алфавите обозначим через $X$. Для английского языка (без знаков
препинания и различия регистра) $X = 26$. Далее каждому из символов
языка мы назначим некоторое число $c$, такое что $0 \le c \le
X$. Например для английского языка можно записать
\begin{equation}
\begin{array}{c}
A \rightarrow 0 \\
B \rightarrow 1 \\
\dots \\
Z \rightarrow 25 \\
\end{array}
\nonumber
\end{equation}

Процедура шифрования \eqref{eqPart3CryptoEncryptClass} описывается
следующим выражением
\begin{equation}
E_{K_i}\left(P_i\right) = P_i + K_i \mod X = C_i,
\label{eqPart3CryptoEncryptVernam}
\end{equation}
где $i$ номер шифруемого символа.

Процедура дешифрования \eqref{eqPart3CryptoDeEncryptClass} описывается
следующим выражением
\begin{equation}
D_{K_i}\left(C_i\right) = C_i - K_i \mod X = P_i,
\label{eqPart3CryptoDeEncryptVernam}
\end{equation}
где $i$ номер шифруемого символа.

Эта процедура легко обобщается на случай двоичных данных, при этом
вместо сложения по модулю используется операция XOR ($a \oplus b$) как
для шифрования, так и для дешифрования :
\begin{table}
\centering
\begin{tabular}{|c|c|c|}
\hline
$a$ & $b$ & $a \oplus b$ \\ \hline
0  & 0 & 0 \\
0  & 1 & 1 \\
1  & 0 & 1 \\
1  & 1 & 0 \\ \hline
\end{tabular}
\caption{XOR $a \oplus b$}
\label{tblXOR}
\end{table}

Клод Шенон показал \cite{bShenonCrypto}, что если ключ действительно
случайный, имеет такую
же длину, как исходное сообщение, и не используется повторно, то
предложенная
схема одноразового блокнота абсолютно защищена.

Согласно Шенону абсолютная защищенность (perfect security) может быть
определена следующим образом.
\begin{definition}
Шифр $\left(E, D\right)$ абсолютно защищен если для любых двух
сообщений одинаковой длины $m_0$ и $m_1$, некоторого шифротекста $c$ и
ключа $k \leftarrow_R K$ вероятности того что исходный текст $m_0$ или
$m_1$ равны:
\begin{equation}
P\left(E\left(m_0, k\right) = c \right) =
P\left(E\left(m_1, k\right) = c \right)
\nonumber
\end{equation}
\end{definition}
Перефразируя это определение можно сказать, что по исходной статистике
шифротекста невозможно получить никакой информации об исходном
сообщении.

\begin{theorem}[Криптостойкость одноразового блокнота]
Схема одноразового блокнота имеет абсолютную защищенность.
\end{theorem}

\begin{proof}
Обозначим через $\left|K\right|$ - число всех возможных ключей длины
$l$. Где $l$ также длина исходных сообщений: $\left|m_{0,1}\right| =
l$. В силу того, что ключ которым зашифровано сообщение определяется
единственным образом:
\begin{equation}
k_{0,1} = c \oplus m_{0,1},
\nonumber
\end{equation}
получаем для вероятностей
\begin{equation}
P\left(E\left(m_0, k\right) = c \right) =
P\left(E\left(m_1, k\right) = c \right) =
\frac{1}{\left|K\right|}.
\nonumber
\end{equation}
\end{proof}

\section{Проблемы классической криптографии}

Если существует абсолютно защищенная криптографическая система (одноразовый блокнот) то
что же не так в классической криптографии? Проблема заключается в
получении ключей, удовлетворяющих требованиям одноразового блокнота
(длина ключа равна длине сообщения, ключ состоит из случайных данных и
ни разу не используется повторно) и передачи этих ключей Бобу и Алисе.

Проблемы возникают как на этапе генерации ключей, \footnote{получение больших
последовательностей случайных чисел является не тривиальной
математической задачей} так и на этапе передачи этих ключей.

Для передачи ключей в классической криптографии используются так
называемые алгоритмы с открытым ключом. Существует несколько
протоколов обмена ключей, основанных на криптографических системах с
открытым ключом. Все они основаны на том, что существует два ключа,
первый из которых, называемый открытым (public key), используется только
для зашифрования, а второй - закрытый (private key) для дешифрования.
Для того чтобы получить закрытый ключ из открытого,
необходимо произвести какую-то сложную математическую
операцию. Например безопасность одной из наиболее популярных систем с
открытым ключом - RSA(см. \ref {AddRSA}),
\rindex{алгоритм RSA}
основана на трудности
факторизации\footnote{разложении на простые множители} больших чисел.

Схема протокола распределения ключа, основанная на криптографии с
открытым ключом, может быть описана следующим образом. На первом этапе
Алиса создает открытый и закрытый ключи и первый из них отсылает Бобу.
Боб со своей стороны создает тот ключ, который хотелось бы иметь и
Алисе и Бобу (который требуется распределить). Этот ключ шифруется
(например по RSA) с помощью открытого ключа Алисы и пересылается
ей. Алиса, получая этот зашифрованный ключ, может расшифровать его с
помощью своего закрытого ключа.

Если злоумышленник (Ева) хочет узнать передаваемый ключ, она должна
решить сложную математическую задачу по факторизации больших
чисел. Считается, но не доказано, что сложность факторизации растет
экспоненциально с ростом числа цифр в числе
\cite{bPhisQuantInfo}.\footnote{Наиболее быстрый из известных
  алгоритмов решает задачу о факторизации числа $N$ за время порядка
  $O\left(exp\left(log^{\frac{1}{3}}N\left(log \, log N\right)^{\frac{2}{3}}\right)\right)$.}
Таким образом при увеличении числа цифр задача быстро становится не решаемой.

В этой схеме имеется несколько проблем. Первая связана с тем что
сложность факторизации не доказана. Мало того, существуют алгоритмы для
квантовых компьютеров - алгоритм Шора(см. \ref {Part4QuantCompShor}),
которые решают задачу о факторизации числа $N$ за время $O\left(log
N\right)$, т. е. за время порядка числа цифр в $N$. Таким образом в
тот момент, когда будет построен квантовый компьютер, все системы,
основанные на RSA\rindex{алгоритм RSA}, утратят свою актуальность.

%% Существует еще одна проблема которая делает системы распределения
%% ключа основанные на открытой криптографии незащищенными. Представим
%% себе ситуацию когда Ева может перехватывать все сообщения Алисы и Боба
%% и подменять их своими, что не является абсолютно нерешаемой задачей в
%% классической теории связи. В этом случае Ева может представиться Бобом для
%% Алисы и Алисой для Боба и таким образом полностью контролировать
%% передачу сообщений между ними и в момент пересылки ключа она сможет
%% его расшифровать.


text:
using System;

namespace Demo
{
    class Program
    {

        static void Main(string[] args)
        {
            double grade = double.Parse(Console.ReadLine());
            if (grade >= 3) Console.WriteLine("Passed!");
            else Console.WriteLine("Failed!");
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
#include "Wt/WAbstractToggleButton"
#include "Wt/WApplication"
#include "Wt/WEnvironment"
#include "Wt/WFormWidget"
#include "Wt/WLabel"
#include "Wt/WTheme"

#include "DomElement.h"
#include "WebUtils.h"

#ifndef WT_DEBUG_JS
#include "js/WFormWidget.min.js"
#endif

namespace Wt {

const char *WFormWidget::CHANGE_SIGNAL = "M_change";
const char *WFormWidget::SELECT_SIGNAL = "select";

WFormWidget::WFormWidget(WContainerWidget *parent)
  : WInteractWidget(parent),
    label_(0),
    validator_(0),
    validateJs_(0),
    filterInput_(0),
    removeEmptyText_(0)
{ }

WFormWidget::~WFormWidget()
{
  if (label_)
    label_->setBuddy((WFormWidget *)0);

  if (validator_)
    validator_->removeFormWidget(this);

  delete removeEmptyText_;
  delete validateJs_;
  delete filterInput_;
}

EventSignal<>& WFormWidget::changed()
{
  return *voidEventSignal(CHANGE_SIGNAL, true);
}

EventSignal<>& WFormWidget::selected()
{
  return *voidEventSignal(SELECT_SIGNAL, true);
}

void WFormWidget::setEnabled(bool enabled)
{
  setDisabled(!enabled);
}

bool WFormWidget::canReceiveFocus() const
{
  return true;
}

int WFormWidget::tabIndex() const
{
  int result = WInteractWidget::tabIndex();

  if (result == std::numeric_limits<int>::min())
    return 0;
  else
    return result;
}

void WFormWidget::propagateSetEnabled(bool enabled)
{
  flags_.set(BIT_ENABLED_CHANGED);
  repaint();
  WInteractWidget::propagateSetEnabled(enabled);
}

void WFormWidget::setReadOnly(bool readOnly)
{
  flags_.set(BIT_READONLY, readOnly);
  flags_.set(BIT_READONLY_CHANGED);

  repaint();
}

bool WFormWidget::isReadOnly() const
{
  return flags_.test(BIT_READONLY);
}

void WFormWidget::setEmptyText(const WString& emptyText)
{
  setPlaceholderText(emptyText);
}

void WFormWidget::setPlaceholderText(const WString& placeholderText)
{
  emptyText_ = placeholderText;

  WApplication* app = WApplication::instance();
  const WEnvironment& env = app->environment();

  if (env.ajax()) {
    if (!emptyText_.empty()) {
      if (!flags_.test(BIT_JS_OBJECT))
	defineJavaScript();
      else
	updateEmptyText();

      if (!removeEmptyText_) {
	removeEmptyText_ = new JSlot(this);

	focussed().connect(*removeEmptyText_);
	blurred().connect(*removeEmptyText_);
	keyWentDown().connect(*removeEmptyText_);

	std::string jsFunction =
	  "function(obj, event) {"
	  """jQuery.data(" + jsRef() + ", 'obj').applyEmptyText();"
	  "}";
	removeEmptyText_->setJavaScript(jsFunction);
      }
    } else {
      delete removeEmptyText_;
      removeEmptyText_ = 0;
    }
  } else {
    setToolTip(placeholderText);
  }
}

void WFormWidget::defineJavaScript(bool force)
{
  if (force || !flags_.test(BIT_JS_OBJECT)) {
    flags_.set(BIT_JS_OBJECT);

    if (!isRendered())
      return;

    WApplication *app = WApplication::instance();

    LOAD_JAVASCRIPT(app, "js/WFormWidget.js", "WFormWidget", wtjs1);

    setJavaScriptMember(" WFormWidget", "new " WT_CLASS ".WFormWidget("
			+ app->javaScriptClass() + ","
			+ jsRef() + ","
			+ emptyText_.jsStringLiteral() + ");");
  }
}

void WFormWidget::render(WFlags<RenderFlag> flags)
{
  if ((flags & RenderFull)) {
    if (flags_.test(BIT_JS_OBJECT))
      defineJavaScript(true);

    if (validator()) {
      WValidator::Result result = validator()->validate(valueText());
      WApplication::instance()->theme()
	->applyValidationStyle(this, result, ValidationInvalidStyle);
    }
  }

  WInteractWidget::render(flags);
}

void WFormWidget::updateEmptyText()
{
  if (isRendered())
    doJavaScript("jQuery.data(" + jsRef() + ", 'obj')"
		 ".setEmptyText(" + emptyText_.jsStringLiteral() + ");");
}

void WFormWidget::applyEmptyText()
{
  if (isRendered() && !emptyText_.empty())
    doJavaScript("jQuery.data(" + jsRef() + ", 'obj').applyEmptyText();");
}

void WFormWidget::refresh()
{
  if (emptyText_.refresh())
    updateEmptyText();

  WInteractWidget::refresh();
}

void WFormWidget::enableAjax()
{
  if (!emptyText_.empty() && toolTip() == emptyText_) {
    setToolTip("");
    setEmptyText(emptyText_);
  }

  WInteractWidget::enableAjax();
}

void WFormWidget::validatorChanged()
{
  std::string validateJS = validator_->javaScriptValidate();
  if (!validateJS.empty()) {
    setJavaScriptMember("wtValidate", validateJS);

    if (!validateJs_) {
      validateJs_ = new JSlot();
      validateJs_->setJavaScript("function(o){" WT_CLASS ".validate(o)}");

      keyWentUp().connect(*validateJs_);
      changed().connect(*validateJs_);
      if (domElementType() != DomElement_SELECT)
	clicked().connect(*validateJs_);
    }
  } else {
    delete validateJs_;
    validateJs_ = 0;
  }

  std::string inputFilter = validator_->inputFilter();

  if (!inputFilter.empty()) {
    if (!filterInput_) {
      filterInput_ = new JSlot();

      keyPressed().connect(*filterInput_);
    }

    Wt::Utils::replace(inputFilter, '/', "\\/");

    filterInput_->setJavaScript
      ("function(o,e){" WT_CLASS ".filter(o,e,"
       + jsStringLiteral(inputFilter) + ")}");
  } else {
    delete filterInput_;
    filterInput_ = 0;
  }

  validate();
}

void WFormWidget::updateDom(DomElement& element, bool all)
{
  const WEnvironment& env = WApplication::instance()->environment();

  bool onChangeHandledElsewhere = dynamic_cast<WAbstractToggleButton *>(this);

  if (!onChangeHandledElsewhere) {
    EventSignal<> *s = voidEventSignal(CHANGE_SIGNAL, false);
    if (s)
      updateSignalConnection(element, *s, "change", all);
  }

  if (flags_.test(BIT_ENABLED_CHANGED) || all) {
    if (!all || !isEnabled())
      element.setProperty(Wt::PropertyDisabled,
			  isEnabled() ? "false" : "true");

    if (!all && isEnabled() && env.agentIsIE()) {
      /*
       * FIXME: implement a workaround for IE, reenabling a checkbox makes
       * the input box loose interactivity.
       */
    }
    flags_.reset(BIT_ENABLED_CHANGED);
  }

  if (flags_.test(BIT_READONLY_CHANGED) || all) {
    if (!all || isReadOnly())
      element.setProperty(Wt::PropertyReadOnly,
			  isReadOnly() ? "true" : "false");
    flags_.reset(BIT_READONLY_CHANGED);
  }

  WInteractWidget::updateDom(element, all);

  if (flags_.test(BIT_VALIDATION_CHANGED)) {
    if (validationToolTip_.empty())
      element.setAttribute("title", toolTip().toUTF8());
    else
      element.setAttribute("title", validationToolTip_.toUTF8());
  }
}

void WFormWidget::propagateRenderOk(bool deep)
{
  flags_.reset(BIT_ENABLED_CHANGED);
  flags_.reset(BIT_VALIDATION_CHANGED);

  WInteractWidget::propagateRenderOk(deep);
}

void WFormWidget::setLabel(WLabel *label)
{
  if (label_) {
    WLabel *l = label_;
    label_ = 0;
    l->setBuddy((WFormWidget *)0);
  }
  label_ = label;

  if (label_)
    label_->setHidden(isHidden());
}

void WFormWidget::setHidden(bool hidden, const WAnimation& animation)
{
  if (label_)
    label_->setHidden(hidden, animation);

  WInteractWidget::setHidden(hidden, animation);
}

void WFormWidget::setToolTip(const WString& text, TextFormat textFormat)
{
  WInteractWidget::setToolTip(text, textFormat);

  if (validator_ && textFormat == PlainText) {
    setJavaScriptMember("defaultTT", text.jsStringLiteral());
    validate();
  }
}

void WFormWidget::setValidator(WValidator *validator)
{
  bool firstValidator = !validator_;

  if (validator_)
    validator_->removeFormWidget(this);

  validator_ = validator;

  if (validator_) {
#ifndef WT_TARGET_JAVA
    if (!validator_->parent())
      WObject::addChild(validator_);
#endif // WT_TARGET_JAVA

    validator_->addFormWidget(this);

    if (firstValidator)
      setToolTip(toolTip());

    validatorChanged();
#ifndef WT_TARGET_JAVA
    if (!validator_->parent())
      WObject::addChild(validator_);
#endif // WT_TARGET_JAVA
  } else {
    if (isRendered())
      WApplication::instance()->theme()
	->applyValidationStyle(this, WValidator::Result(), ValidationNoStyle);

    delete validateJs_;
    validateJs_ = 0;
    delete filterInput_;
    filterInput_ = 0;
  }
}

WValidator::State WFormWidget::validate()
{
  if (validator()) {
    WValidator::Result result = validator()->validate(valueText());

    if (isRendered())
      WApplication::instance()->theme()
	->applyValidationStyle(this, result, ValidationInvalidStyle);

    if (validationToolTip_ != result.message()) {
      validationToolTip_ = result.message();
      flags_.set(BIT_VALIDATION_CHANGED);
      repaint();
    }

    validated_.emit(result);

    return result.state();
  } else
    return WValidator::Valid;
}

std::string WFormWidget::formName() const
{
  return id();
}

}


text:
package com.example.widgetexample_01;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.widget.RemoteViews;
import android.widget.Toast;

public class MyAppWidgetProvider extends AppWidgetProvider
{
	@Override
	public void onUpdate (Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds)
	{
		for (int i = 0; i < appWidgetIds.length; i++)
		{
			int currentWidgetId = appWidgetIds[i];

			String url = "https://www.youtube.com/playlist?list=PLQCiiajdpppoOVoSi0d7Gtmfoohb_B8n2";

			Intent intent = new Intent(Intent.ACTION_VIEW);
			intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			intent.setData(Uri.parse(url));

			PendingIntent pending = PendingIntent.getActivity(context, 0,
					intent, 0);
			RemoteViews views = new RemoteViews(context.getPackageName(),
					R.layout.widgetlayout);
			views.setOnClickPendingIntent(R.id.button1, pending);

			appWidgetManager.updateAppWidget(currentWidgetId, views);
			Toast.makeText(context, "widget added", Toast.LENGTH_SHORT).show();
		}
	}
}


text:
(function () {
  "use strict";

  angular
    .module('mnSearch', [])
    .directive('mnSearch', mnSearchDirective);

  function mnSearchDirective() {

    var mnSearch = {
      restrict: 'AE',
      scope: {
        mnSearch: "=",
        mnPlaceholder: "@",
        mnHideButton: "="
      },
      templateUrl: 'app/components/directives/mn_search/mn_search.html',
      controller: controller,
      controllerAs: "mnSearchCtl",
      bindToController: true
    };

    return mnSearch;

    function controller() {
      var vm = this;
      vm.hideFilter = hideFilter;
      vm.showFilter = showFilter;

      function hideFilter() {
        vm.mnSearch = "";
        vm.showFilterFlag = false;
      }
      function showFilter() {
        vm.showFilterFlag = true;
        vm.focusFilterField = true;
      }
    }
  }
})();


text:
<?php

if (!function_exists('loggr')) {

    /**
     * Helper function for calling add() method on underlying Loggr service
     *
     * @param string $message
     * @param \App\Models\User|int $owner
     * @return LogMessage|bool
     */
    function loggr($message, $owner = null, $data = null)
    {
        return \C4studio\Loggr\Facades\Loggr::add($message, $owner, $data);
    }

}


text:
package quibit

import (
	"bytes"
	"crypto/sha512"
	"encoding/binary"
)

// Used as a fixed-length description of a frame
type Header struct {
	Magic    uint32   // Known magic number
	Command  uint8    // How to interpret payload
	Type     uint8    // How to interpret payload
	Checksum [48]byte // SHA-384 Checksum of Payload
	Length   uint32   // Length of Payload
}

// Configure a new header given the frame payload
func (h *Header) Configure(data []byte) {
	h.Magic = MAGIC
	h.Checksum = sha512.Sum384(data)
	h.Length = uint32(len(data))
}

// Serialize Header for sending over the wire
func (h *Header) ToBytes() ([]byte, error) {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.BigEndian, h)
	return buf.Bytes(), err
}

// Unserialize header from the wire
func (h *Header) FromBytes(b []byte) error {
	buf := bytes.NewReader(b)
	err := binary.Read(buf, binary.BigEndian, h)
	return err
}


text:
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
#pragma warning(disable:4819)
#  define WINDOWS_LEAN_AND_MEAN
#  define NOMINMAX
#  include <windows.h>
#endif

#include "FreeImage.h"
#include "Exceptions.h"

#include <string.h>
#include <fstream>
#include <iostream>

#include <cuda_runtime.h>
#include <npp.h>               // CUDA NPP Definitions

#include <helper_cuda.h>       // helper for CUDA Error handling and initialization
#include <helper_string.h>     // helper for string parsing

inline int cudaDeviceInit(int argc, const char **argv)
{
    int deviceCount;
    checkCudaErrors(cudaGetDeviceCount(&deviceCount));

    if (deviceCount == 0)
    {
        std::cerr << "CUDA error: no devices supporting CUDA." << std::endl;
        exit(EXIT_FAILURE);
    }

    int dev = findCudaDevice(argc, argv);

    cudaDeviceProp deviceProp;
    cudaGetDeviceProperties(&deviceProp, dev);
    std::cerr << "cudaSetDevice GPU" << dev << " = " << deviceProp.name << std::endl;

    checkCudaErrors(cudaSetDevice(dev));

    return dev;
}

bool printfNPPinfo(int argc, char *argv[], int cudaVerMajor, int cudaVerMinor)
{
    const NppLibraryVersion *libVer   = nppGetLibVersion();

    printf("NPP Library Version %d.%d.%d\n", libVer->major, libVer->minor, libVer->build);

	int driverVersion, runtimeVersion;
    cudaDriverGetVersion(&driverVersion);
    cudaRuntimeGetVersion(&runtimeVersion);

	printf("  CUDA Driver  Version: %d.%d\n", driverVersion/1000, (driverVersion%100)/10);
	printf("  CUDA Runtime Version: %d.%d\n", runtimeVersion/1000, (runtimeVersion%100)/10);

	bool bVal = checkCudaCapabilities(cudaVerMajor, cudaVerMinor);
	return bVal;
}

// Error handler for FreeImage library.
//  In case this handler is invoked, it throws an NPP exception.
extern "C" void
FreeImageErrorHandler(FREE_IMAGE_FORMAT oFif, const char *zMessage)
{
    throw npp::Exception(zMessage);
}

std::ostream &
operator <<(std::ostream &rOutputStream, const FIBITMAP &rBitmap)
{
    unsigned int nImageWidth    = FreeImage_GetWidth(const_cast<FIBITMAP *>(&rBitmap));
    unsigned int nImageHeight   = FreeImage_GetHeight(const_cast<FIBITMAP *>(&rBitmap));
    unsigned int nPitch         = FreeImage_GetPitch(const_cast<FIBITMAP *>(&rBitmap));
    unsigned int nBPP           = FreeImage_GetBPP(const_cast<FIBITMAP *>(&rBitmap));

    FREE_IMAGE_COLOR_TYPE eType = FreeImage_GetColorType(const_cast<FIBITMAP *>(&rBitmap));

    rOutputStream << "Size  (" << nImageWidth << ", " << nImageHeight << ")\n";
    rOutputStream << "Pitch "  << nPitch << "\n";
    rOutputStream << "Type  ";

    switch (eType)
    {
        case FIC_MINISWHITE:
            rOutputStream << "FIC_MINISWHITE\n";
            break;

        case FIC_MINISBLACK:
            rOutputStream << "FIC_MINISBLACK\n";
            break;

        case FIC_RGB:
            rOutputStream << "FIC_RGB\n";
            break;

        case FIC_PALETTE:
            rOutputStream << "FIC_PALETTE\n";
            break;

        case FIC_RGBALPHA:
            rOutputStream << "FIC_RGBALPHA\n";
            break;

        case FIC_CMYK:
            rOutputStream << "FIC_CMYK\n";
            break;

        default:
            rOutputStream << "Unknown pixel format.\n";
    }

    rOutputStream << "BPP   " << nBPP << std::endl;

    return rOutputStream;
}

int
main(int argc, char *argv[])
{
    printf("%s Starting...\n\n", argv[0]);

    try
    {
        std::string sFilename;
        char *filePath;

        // set your own FreeImage error handler
        FreeImage_SetOutputMessage(FreeImageErrorHandler);

        cudaDeviceInit(argc, (const char **)argv);

        // Min spec is SM 1.0 devices
        if (printfNPPinfo(argc, argv, 1, 0) == false)
        {
            cudaDeviceReset();
            exit(EXIT_SUCCESS);
        }

        if (checkCmdLineFlag(argc, (const char **)argv, "input"))
        {
            getCmdLineArgumentString(argc, (const char **)argv, "input", &filePath);
        }
        else
        {
            filePath = sdkFindFilePath("Lena.pgm", argv[0]);
        }

        if (filePath)
        {
            sFilename = filePath;
        }
        else
        {
            sFilename = "Lena.pgm";
        }

        // if we specify the filename at the command line, then we only test sFilename
        // otherwise we will check both sFilename[0,1]
        int file_errors = 0;
        std::ifstream infile(sFilename.data(), std::ifstream::in);

        if (infile.good())
        {
            std::cout << "freeImageInteropNPP opened: <" << sFilename.data() << "> successfully!" << std::endl;
            file_errors = 0;
            infile.close();
        }
        else
        {
            std::cout << "freeImageInteropNPP unable to open: <" << sFilename.data() << ">" << std::endl;
            file_errors++;
            infile.close();
        }

        if (file_errors > 0)
        {
            exit(EXIT_FAILURE);
        }

        std::string sResultFilename = sFilename;

        std::string::size_type dot = sResultFilename.rfind('.');

        if (dot != std::string::npos)
        {
            sResultFilename = sResultFilename.substr(0, dot);
        }

        sResultFilename += "_boxFilterFII.pgm";

        if (checkCmdLineFlag(argc, (const char **)argv, "output"))
        {
            char *outputFilePath;
            getCmdLineArgumentString(argc, (const char **)argv, "output", &outputFilePath);
            sResultFilename = outputFilePath;
        }

        FREE_IMAGE_FORMAT eFormat = FreeImage_GetFileType(sFilename.c_str());

        // no signature? try to guess the file format from the file extension
        if (eFormat == FIF_UNKNOWN)
        {
            eFormat = FreeImage_GetFIFFromFilename(sFilename.c_str());
        }

        NPP_ASSERT(eFormat != FIF_UNKNOWN);
        // check that the plugin has reading capabilities ...
        FIBITMAP *pBitmap;

        if (FreeImage_FIFSupportsReading(eFormat))
        {
            pBitmap = FreeImage_Load(eFormat, sFilename.c_str());
        }

        NPP_ASSERT(pBitmap != 0);
        // Dump the bitmap information to the console
        std::cout << (*pBitmap) << std::endl;
        // make sure this is an 8-bit single channel image
        NPP_ASSERT(FreeImage_GetColorType(pBitmap) == FIC_MINISBLACK);
        NPP_ASSERT(FreeImage_GetBPP(pBitmap) == 8);

        unsigned int nImageWidth  = FreeImage_GetWidth(pBitmap);
        unsigned int nImageHeight = FreeImage_GetHeight(pBitmap);
        unsigned int nSrcPitch    = FreeImage_GetPitch(pBitmap);
        unsigned char *pSrcData  = FreeImage_GetBits(pBitmap);

        int nSrcPitchCUDA;
        Npp8u *pSrcImageCUDA = nppiMalloc_8u_C1(nImageWidth, nImageHeight, &nSrcPitchCUDA);
        NPP_ASSERT_NOT_NULL(pSrcImageCUDA);
        // copy image loaded via FreeImage to into CUDA device memory, i.e.
        // transfer the image-data up to the GPU's video-memory
        NPP_CHECK_CUDA(cudaMemcpy2D(pSrcImageCUDA, nSrcPitchCUDA, pSrcData, nSrcPitch,
                                    nImageWidth, nImageHeight, cudaMemcpyHostToDevice));

        // define size of the box filter
        const NppiSize  oMaskSize   = {7, 7};
        const NppiPoint oMaskAchnor = {0, 0};
        // compute maximal result image size
        const NppiSize  oSizeROI = {(int)nImageWidth  - (oMaskSize.width - 1),
                                    (int)nImageHeight - (oMaskSize.height - 1)
                                   };
        // allocate result image memory
        int nDstPitchCUDA;
        Npp8u *pDstImageCUDA = nppiMalloc_8u_C1(oSizeROI.width, oSizeROI.height, &nDstPitchCUDA);
        NPP_ASSERT_NOT_NULL(pDstImageCUDA);
        NPP_CHECK_NPP(nppiFilterBox_8u_C1R(pSrcImageCUDA, nSrcPitchCUDA, pDstImageCUDA, nDstPitchCUDA,
                                           oSizeROI, oMaskSize, oMaskAchnor));
        // create the result image storage using FreeImage so we can easily
        // save
        FIBITMAP *pResultBitmap = FreeImage_Allocate(oSizeROI.width, oSizeROI.height, 8 /* bits per pixel */);
        NPP_ASSERT_NOT_NULL(pResultBitmap);
        unsigned int nResultPitch   = FreeImage_GetPitch(pResultBitmap);
        unsigned char *pResultData = FreeImage_GetBits(pResultBitmap);

        NPP_CHECK_CUDA(cudaMemcpy2D(pResultData, nResultPitch, pDstImageCUDA, nDstPitchCUDA,
                                    oSizeROI.width, oSizeROI.height, cudaMemcpyDeviceToHost));
        // now save the result image
        bool bSuccess;
        bSuccess = FreeImage_Save(FIF_PGM, pResultBitmap, sResultFilename.c_str(), 0) == TRUE;
        NPP_ASSERT_MSG(bSuccess, "Failed to save result image.");

        //free nppiImage
        nppiFree(pSrcImageCUDA);
        nppiFree(pDstImageCUDA);

        cudaDeviceReset();
        exit(EXIT_SUCCESS);
    }
    catch (npp::Exception &rException)
    {
        std::cerr << "Program error! The following exception occurred: \n";
        std::cerr << rException << std::endl;
        std::cerr << "Aborting." << std::endl;
        exit(EXIT_FAILURE);
    }
    catch (...)
    {
        std::cerr << "Program error! An unknow type of exception occurred. \n";
        std::cerr << "Aborting." << std::endl;
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}


text:
<?

namespace rude;

define('RUDE_HTML_STATE_DATA',                                           1);
define('RUDE_HTML_STATE_RCDATA',                                         2);
define('RUDE_HTML_STATE_RAWTEXT',                                        3);
define('RUDE_HTML_STATE_SCRIPT_DATA',                                    4);
define('RUDE_HTML_STATE_PLAINTEXT',                                      5);
define('RUDE_HTML_STATE_TAG_OPEN',                                       6);
define('RUDE_HTML_STATE_END_TAG_OPEN',                                   7);
define('RUDE_HTML_STATE_TAG_NAME',                                       8);
define('RUDE_HTML_STATE_RCDATA_LESS_THAN_SIGN',                          9);
define('RUDE_HTML_STATE_RCDATA_END_TAG_OPEN',                           10);
define('RUDE_HTML_STATE_RCDATA_END_TAG_NAME',                           11);
define('RUDE_HTML_STATE_RAWTEXT_LESS_THAN_SIGN',                        12);
define('RUDE_HTML_STATE_RAWTEXT_END_TAG_OPEN',                          13);
define('RUDE_HTML_STATE_RAWTEXT_END_TAG_NAME',                          14);
define('RUDE_HTML_STATE_SCRIPT_DATA_LESS_THAN_SIGN',                    15);
define('RUDE_HTML_STATE_SCRIPT_DATA_END_TAG_OPEN',                      16);
define('RUDE_HTML_STATE_SCRIPT_DATA_END_TAG_NAME',                      17);
define('RUDE_HTML_STATE_SCRIPT_DATA_ESCAPE_START',                      18);
define('RUDE_HTML_STATE_SCRIPT_DATA_ESCAPE_START_DASH',                 19);
define('RUDE_HTML_STATE_SCRIPT_DATA_ESCAPED',                           20);
define('RUDE_HTML_STATE_SCRIPT_DATA_ESCAPED_DASH',                      21);
define('RUDE_HTML_STATE_SCRIPT_DATA_ESCAPED_DASH_DASH',                 22);
define('RUDE_HTML_STATE_SCRIPT_DATA_ESCAPED_LESS_THAN_SIGN',            23);
define('RUDE_HTML_STATE_SCRIPT_DATA_ESCAPED_END_TAG_OPEN',              24);
define('RUDE_HTML_STATE_SCRIPT_DATA_ESCAPED_END_TAG_NAME',              25);
define('RUDE_HTML_STATE_SCRIPT_DATA_DOUBLE_ESCAPE_START',               26);
define('RUDE_HTML_STATE_SCRIPT_DATA_DOUBLE_ESCAPED',                    27);
define('RUDE_HTML_STATE_SCRIPT_DATA_DOUBLE_ESCAPED_DASH',               28);
define('RUDE_HTML_STATE_SCRIPT_DATA_DOUBLE_ESCAPED_DASH_DASH',          29);
define('RUDE_HTML_STATE_SCRIPT_DATA_DOUBLE_ESCAPED_LESS_THAN_SIGN',     30);
define('RUDE_HTML_STATE_SCRIPT_DATA_DOUBLE_ESCAPE_END',                 31);
define('RUDE_HTML_STATE_BEFORE_ATTRIBUTE_NAME',                         32);
define('RUDE_HTML_STATE_ATTRIBUTE_NAME',                                33);
define('RUDE_HTML_STATE_AFTER_ATTRIBUTE_NAME',                          34);
define('RUDE_HTML_STATE_BEFORE_ATTRIBUTE_VALUE',                        35);
define('RUDE_HTML_STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED',                 36);
define('RUDE_HTML_STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED',                 37);
define('RUDE_HTML_STATE_ATTRIBUTE_VALUE_UNQUOTED',                      38);
define('RUDE_HTML_STATE_AFTER_ATTRIBUTE_VALUE_QUOTED',                  39);
define('RUDE_HTML_STATE_SELF_CLOSING_START_TAG',                        40);
define('RUDE_HTML_STATE_BOGUS_COMMENT',                                 41);
define('RUDE_HTML_STATE_MARKUP_DECLARATION_OPEN',                       42);
define('RUDE_HTML_STATE_COMMENT_START',                                 43);
define('RUDE_HTML_STATE_COMMENT_START_DASH',                            44);
define('RUDE_HTML_STATE_COMMENT',                                       45);
define('RUDE_HTML_STATE_COMMENT_LESS_THAN_SIGN',                        46);
define('RUDE_HTML_STATE_COMMENT_LESS_THAN_SIGN_BANG',                   47);
define('RUDE_HTML_STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH',              48);
define('RUDE_HTML_STATE_COMMENT_LESS_THAN_SIGN_BANG_DASH_DASH',         49);
define('RUDE_HTML_STATE_COMMENT_END_DASH',                              50);
define('RUDE_HTML_STATE_COMMENT_END',                                   51);
define('RUDE_HTML_STATE_COMMENT_END_BANG',                              52);
define('RUDE_HTML_STATE_DOCTYPE',                                       53);
define('RUDE_HTML_STATE_BEFORE_DOCTYPE_NAME',                           54);
define('RUDE_HTML_STATE_DOCTYPE_NAME',                                  55);
define('RUDE_HTML_STATE_AFTER_DOCTYPE_NAME',                            56);
define('RUDE_HTML_STATE_AFTER_DOCTYPE_PUBLIC_KEYWORD',                  57);
define('RUDE_HTML_STATE_BEFORE_DOCTYPE_PUBLIC_IDENTIFIER',              58);
define('RUDE_HTML_STATE_DOCTYPE_PUBLIC_IDENTIFIER_DOUBLE_QUOTED',       59);
define('RUDE_HTML_STATE_DOCTYPE_PUBLIC_IDENTIFIER_SINGLE_QUOTED',       60);
define('RUDE_HTML_STATE_AFTER_DOCTYPE_PUBLIC_IDENTIFIER',               61);
define('RUDE_HTML_STATE_BETWEEN_DOCTYPE_PUBLIC_AND_SYSTEM_IDENTIFIERS', 62);
define('RUDE_HTML_STATE_AFTER_DOCTYPE_SYSTEM_KEYWORD',                  63);
define('RUDE_HTML_STATE_BEFORE_DOCTYPE_SYSTEM_IDENTIFIER',              64);
define('RUDE_HTML_STATE_DOCTYPE_SYSTEM_IDENTIFIER_DOUBLE_QUOTED',       65);
define('RUDE_HTML_STATE_DOCTYPE_SYSTEM_IDENTIFIER_SINGLE_QUOTED',       66);
define('RUDE_HTML_STATE_AFTER_DOCTYPE_SYSTEM_IDENTIFIER',               67);
define('RUDE_HTML_STATE_BOGUS_DOCTYPE',                                 68);
define('RUDE_HTML_STATE_CDATA_SECTION',                                 69);
define('RUDE_HTML_STATE_CDATA_SECTION_BRACKET',                         70);
define('RUDE_HTML_STATE_CDATA_SECTION_END',                             71);
define('RUDE_HTML_STATE_CHARACTER_REFERENCE',                           72);
define('RUDE_HTML_STATE_NUMERIC_CHARACTER_REFERENCE',                   73);
define('RUDE_HTML_STATE_HEXADECIMAL_CHARACTER_REFERENCE_START',         74);
define('RUDE_HTML_STATE_DECIMAL_CHARACTER_REFERENCE_START',             75);
define('RUDE_HTML_STATE_HEXADECIMAL_CHARACTER_REFERENCE',               76);
define('RUDE_HTML_STATE_DECIMAL_CHARACTER_REFERENCE',                   77);
define('RUDE_HTML_STATE_NUMERIC_CHARACTER_REFERENCE_END',               78);
define('RUDE_HTML_STATE_CHARACTER_REFERENCE_END',                       79);

define('RUDE_HTML_CHAR_NULL',            "\0");
define('RUDE_HTML_CHAR_EOF',             'EOF');
define('RUDE_HTML_CHAR_REPLACEMENT',     '�');
define('RUDE_HTML_CHAR_SOLIDUS',         '/');
define('RUDE_HTML_CHAR_LESS_THAN_SIGN',  '<');
define('RUDE_HTML_CHAR_SPACE',           ' ');
define('RUDE_HTML_CHAR_TAB',             0x09);
define('RUDE_HTML_CHAR_LINE_FEED',       0x0A);
define('RUDE_HTML_CHAR_FORM_FEED',       0x0C);
define('RUDE_HTML_CHAR_CARRIAGE_RETURN', 0x0D);

define('RUDE_HTML_OPTION_CONSUME', 1);
define('RUDE_HTML_OPTION_CONSUME_VALUE_NEXT', 1);

define('RUDE_HTML_OPTION_DEFAULT', 2);
define('RUDE_HTML_OPTION_DEFAULT_VALUE_EMIT', 1);

define('RUDE_HTML_OPTION_CHARS', 3);

define('RUDE_HTML_ACTION_STATE',                  1);
define('RUDE_HTML_ACTION_STATE_RETURN',           2);
define('RUDE_HTML_ACTION_PARSE_ERROR',            3);
define('RUDE_HTML_ACTION_EMIT',                   4);
define('RUDE_HTML_ACTION_EMIT_CURRENT_CHAR',      5);
define('RUDE_HTML_ACTION_EMIT_CURRENT_TAG',       6);
define('RUDE_HTML_ACTION_RECONSUME',              9);
define('RUDE_HTML_ACTION_CREATE',                10);
define('RUDE_HTML_ACTION_ASCII_UPPERCASE',       11);
define('RUDE_HTML_ACTION_ASCII_LOWERCASE',       12);

define('RUDE_HTML_CREATE_TAG',     1);
define('RUDE_HTML_CREATE_TAG_END', 2);
define('RUDE_HTML_CREATE_COMMENT', 3);

class html_tokenizer
{
	# http://w3c.github.io/html/syntax.html#writing-html-documents-elements

	private $html;

	private $chars = [];
	private $chars_amount = 0;

	private $char;

	private $offset = 0;

//	private $elements_special = [];
//	private $elements_formatting = [];

	private $data_states = [];

//	private $elements_void      = [];
//	private $elements_raw       = [];
//	private $elements_escapable = [];

	private $state;
	private $state_return;

	/** @var html_ascii */
	private $ascii;

	/** @var html_tokens */
	private $tokens;

	public function __construct($html)
	{
		# 8.2.2.5. Preprocessing the input stream
		#
		# https://w3c.github.io/html/syntax.html#preprocessing-the-input-stream
		#
		# U+000D CARRIAGE RETURN (CR) characters and U+000A LINE FEED (LF) characters are treated specially. Any LF character
		# that immediately follows a CR character must be ignored, and all CR characters must then be converted to LF charact
		# ers. Thus, newlines in HTML DOMs are represented by LF characters, and there are never any CR characters in the inp
		# ut to the tokenization stage.

		$this->html = strings::replace($html, [RUDE_HTML_CHAR_LINE_FEED . RUDE_HTML_CHAR_CARRIAGE_RETURN, RUDE_HTML_CHAR_CARRIAGE_RETURN], RUDE_HTML_CHAR_LINE_FEED);

		$this->chars = strings::chars($this->html);
		$this->chars[] = RUDE_HTML_CHAR_EOF;

		$this->chars_amount = count($this->chars);

		$this->ascii = new html_ascii();
		$this->tokens = new html_tokens();

//
//		$this->elements_void      = array_flip(['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
//		$this->elements_raw       = array_flip(['script', 'style']);
//		$this->elements_escapable = array_flip(['textarea', 'title']);

		# http://w3c.github.io/html/syntax.html#special

//		$this->elements_special   = array_flip(['area', 'article', 'aside', 'base', 'basefont', 'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col', 'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'iframe', 'img', 'input', 'li', 'link', 'listing', 'main', 'marquee', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol', 'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source', 'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp', 'mi', 'mo', 'mn', 'ms', 'mtext', 'annotation-xml', 'foreignObject', 'desc', 'title']);

		# http://w3c.github.io/html/syntax.html#formatting

//		$this->elements_formatting = array_flip(['']);

//		$this->states_special = array_flip(['consume', 'default']);

		# http://w3c.github.io/html/syntax.html#tokenizer-data-state

	}

	public function parse()
	{
		# http://w3c.github.io/html/syntax.html#data-state

		# The state machine must start in the data state.

		static::state(RUDE_HTML_STATE_DATA);

		$this->offset = 0;

		while ($this->offset < $this->chars_amount)
		{
			console::write(console::colorize($this->state, false, 'yellow'));

			static::tokenize();
		}
	}

	private function tokenize()
	{
		#######################################################
		# https://w3c.github.io/html/syntax.html#tokenization #

		switch ($this->state)
		{
			# 8.2.4.1. Data state
			#
			# Consume the next input character:
			# ------------------------------------------------------------------------------------------------------------
			# U+0026 AMPERSAND (&)      | Set the return state to the data state. Switch to the character reference state.
			# U+003C LESS-THAN SIGN (<) | Switch to the tag open state.
			# U+0000 NULL               | Parse error. Emit the current input character as a character token.
			# EOF                       | Emit an end-of-file token.
			# Anything else             | Emit the current input character as a character token.

			case RUDE_HTML_STATE_DATA:

				static::char_consume();

				switch ($this->char)
				{
					case '&': static::state(RUDE_HTML_STATE_CHARACTER_REFERENCE, RUDE_HTML_STATE_DATA); break;
					case '<': static::state(RUDE_HTML_STATE_TAG_OPEN);                                  break;

					case RUDE_HTML_CHAR_NULL: static::parse_error(); static::emit_char_current(); break;
					case RUDE_HTML_CHAR_EOF:  static::create_token_eof();                                 break;

					default: static::emit_char_current();
				}

				break;

			# 8.2.4.2. RCDATA state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------
			# U+0026 AMPERSAND (&)      | Set the return state to the RCDATA state. Switch to the character reference state.
			# U+003C LESS-THAN SIGN (<) | Switch to the RCDATA less-than sign state.
			# U+0000 NULL               | Parse error. Emit a U+FFFD REPLACEMENT CHARACTER character token.
			# EOF                       | Emit an end-of-file token.
			# Anything else             | Emit the current input character as a character token.

			case RUDE_HTML_STATE_RCDATA:

				static::char_consume();

				switch ($this->char)
				{
					case '&': static::state(RUDE_HTML_STATE_CHARACTER_REFERENCE, RUDE_HTML_STATE_RCDATA); break;
					case '<': static::state(RUDE_HTML_STATE_RCDATA_LESS_THAN_SIGN);                       break;

					case RUDE_HTML_CHAR_NULL: static::parse_error(); static::emit_char_replacement(); break;
					case RUDE_HTML_CHAR_EOF:  static::create_token_eof();                                     break;

					default: static::emit_char_current();
				}

				break;

			# 8.2.4.3. RAWTEXT state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------
			# U+003C LESS-THAN SIGN (<) | Switch to the RAWTEXT less-than sign state.
			# U+0000 NULL               | Parse error. Emit a U+FFFD REPLACEMENT CHARACTER character token.
			# EOF                       | Emit an end-of-file token.
			# Anything else             | Emit the current input character as a character token.

			case RUDE_HTML_STATE_RAWTEXT:

				static::char_consume();

				switch ($this->char)
				{
					case '<': static::state(RUDE_HTML_STATE_RAWTEXT_LESS_THAN_SIGN); break;

					case RUDE_HTML_CHAR_NULL: static::parse_error(); static::emit_char_replacement(); break;
					case RUDE_HTML_CHAR_EOF:  static::create_token_eof();                                     break;

					default: static::emit_char_current();
				}

				break;

			# 8.2.4.4. Script data state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------
			# U+003C LESS-THAN SIGN (<) | Switch to the script data less-than sign state.
			# U+0000 NULL               | Parse error. Emit a U+FFFD REPLACEMENT CHARACTER character token.
			# EOF                       | Emit an end-of-file token.
			# Anything else             | Emit the current input character as a character token.

			case RUDE_HTML_STATE_SCRIPT_DATA:

				static::char_consume();

				switch ($this->char)
				{
					case '<': static::state(RUDE_HTML_STATE_SCRIPT_DATA_LESS_THAN_SIGN); break;

					case RUDE_HTML_CHAR_NULL: static::parse_error(); static::emit_char_replacement(); break;
					case RUDE_HTML_CHAR_EOF:  static::create_token_eof();                                     break;

					default: static::emit_char_current();
				}

				break;

			# 8.2.4.5. PLAINTEXT state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------
			# U+0000 NULL   Parse error. Emit a U+FFFD REPLACEMENT CHARACTER character token.
			# EOF           Emit an end-of-file token.
			# Anything else Emit the current input character as a character token.

			case RUDE_HTML_STATE_PLAINTEXT:

				static::char_consume();

				switch ($this->char)
				{
					case RUDE_HTML_CHAR_NULL: static::parse_error(); static::emit_char_replacement(); break;
					case RUDE_HTML_CHAR_EOF:  static::create_token_eof();                                     break;

					default: static::emit_char_current();
				}

				break;

			# 8.2.4.6. Tag open state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------------------------------------------------
			# U+0021 EXCLAMATION MARK (!) | Switch to the markup declaration open state.
			# U+002F SOLIDUS (/)          | Switch to the end tag open state.
			# ASCII letter                | Create a new start tag token, set its tag name to the empty string. Reconsume in the tag name state.
			# U+003F QUESTION MARK (?)    | Parse error. Create a comment token whose data is the empty string. Reconsume in the bogus comment state.
			# Anything else               | Parse error. Emit a U+003C LESS-THAN SIGN character token. Reconsume in the data state.

			case RUDE_HTML_STATE_TAG_OPEN:

				static::char_consume();

				switch ($this->char)
				{
					case '!': static::state(RUDE_HTML_STATE_MARKUP_DECLARATION_OPEN); break;
					case '/': static::state(RUDE_HTML_STATE_END_TAG_OPEN);            break;

					case '?':
						static::parse_error();
						static::create_comment();
						static::state_reconsume(RUDE_HTML_STATE_BOGUS_COMMENT);
						break;

					default:

						if (isset($this->ascii_alphabetic[$this->char]))
						{
							static::create_tag_start();

							console::log('name to empty string', RUDE_E_SUCCESS);
							# set its tag name to the empty string
							static::state_reconsume(RUDE_HTML_STATE_TAG_NAME);
						}
						else
						{
							static::parse_error();
							static::emit_char_less_than_sign();
							static::state_reconsume(RUDE_HTML_STATE_DATA);
						}
				}

				break;

			# 8.2.4.7. End tag open state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------------------------------------------------
			# ASCII letter                 | Create a new end tag token, set its tag name to the empty string. Reconsume in the tag name state.
			# U+003E GREATER-THAN SIGN (>) | Parse error. Switch to the data state.
			# EOF                          | Parse error. Emit a U+003C LESS-THAN SIGN character token, a U+002F SOLIDUS character token and an end-of-file token.
			# Anything else                | Parse error. Create a comment token whose data is the empty string. Reconsume in the bogus comment state.

			case RUDE_HTML_STATE_END_TAG_OPEN:

				static::char_consume();

				switch ($this->char)
				{
					case '>':
						static::parse_error();
						static::state(RUDE_HTML_STATE_DATA);
						break;

					case RUDE_HTML_CHAR_EOF:
						static::parse_error();
						static::emit_char_less_than_sign();
						static::emit_char_solidus();
						static::create_token_eof();
						break;

					default:

						if (isset($this->ascii_alphabetic[$this->char]))
						{
							static::create_tag_end();
							# set its tag name to the empty string
							static::state_reconsume(RUDE_HTML_STATE_TAG_NAME);
						}
						else
						{
							static::parse_error();
							static::create_comment();
							static::state_reconsume(RUDE_HTML_STATE_BOGUS_COMMENT);
						}
				}

				break;

			# 8.2.4.8. Tag name state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------------------------------------------------
			# U+0009 CHARACTER TABULATION (tab) |
			# U+000A LINE FEED (LF)             |
			# U+000C FORM FEED (FF)             |
			# U+0020 SPACE                      | Switch to the before attribute name state.
			# U+002F SOLIDUS (/)                | Switch to the self-closing start tag state.
			# U+003E GREATER-THAN SIGN (>)      | Switch to the data state. Emit the current tag token.
			# Uppercase ASCII letter            | Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current tag token's tag name.
			# U+0000 NULL                       | Parse error. Append a U+FFFD REPLACEMENT CHARACTER character to the current tag token's tag name.
			# EOF                               | Parse error. Emit an end-of-file token.
			# Anything else                     | Append the current input character to the current tag token's tag name.

			case RUDE_HTML_STATE_TAG_NAME:

				static::char_consume();

				switch ($this->char)
				{
					case RUDE_HTML_CHAR_TAB:
					case RUDE_HTML_CHAR_LINE_FEED:
					case RUDE_HTML_CHAR_FORM_FEED:
					case RUDE_HTML_CHAR_SPACE:
						static::state(RUDE_HTML_STATE_BEFORE_ATTRIBUTE_NAME);
						break;

					case '/':
						static::state(RUDE_HTML_STATE_SELF_CLOSING_START_TAG);
						break;

					case '>':
						static::state(RUDE_HTML_STATE_DATA);
						static::emit_tag(); # Emit the current tag token.
						break;

					case RUDE_HTML_CHAR_NULL:
						static::parse_error();

						$this->tokens->token->name .= RUDE_HTML_CHAR_REPLACEMENT;
						break;

					case RUDE_HTML_CHAR_EOF:
						static::parse_error();
						static::create_token_eof();
						break;

					default:
						$this->tokens->token->name .= $this->ascii->to_lowercase($this->char);
				}

				break;

			# 8.2.4.9. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.10. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.11. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.12. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.13. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.14. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.15. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.16. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.17. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.18. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.19. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.20. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.21. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.22. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.23. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.24. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.25. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.26. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.27. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.28. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.29. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.30. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.31. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.32. Before attribute name state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------------------------------------------------
			# U+0009 CHARACTER TABULATION (tab) |
			# U+000A LINE FEED (LF)             |
			# U+000C FORM FEED (FF)             |
			# U+0020 SPACE                      | Ignore the character.
			# U+002F SOLIDUS (/)                |
			# U+003E GREATER-THAN SIGN (>)      |
			# EOF                               | Reconsume in the after attribute name state.
			# U+003D EQUALS SIGN (=)            | Parse error. Start a new attribute in the current tag token. Set that attribute's name to the current input character, and its value to the empty string. Switch to the attribute name state.
			# Anything else                     | Start a new attribute in the current tag token. Set that attribute's name and value to the empty string. Reconsume in the attribute name state.

			case RUDE_HTML_STATE_BEFORE_ATTRIBUTE_NAME:

				static::char_consume();

				switch ($this->char)
				{
					case RUDE_HTML_CHAR_TAB:
					case RUDE_HTML_CHAR_LINE_FEED:
					case RUDE_HTML_CHAR_FORM_FEED:
					case RUDE_HTML_CHAR_SPACE:
						# Ignore the character
						break;

					case '/':
					case '>':
					case RUDE_HTML_CHAR_EOF:
						static::state_reconsume(RUDE_HTML_STATE_AFTER_ATTRIBUTE_NAME);
						break;

					case '=':
						static::parse_error();

						# Start a new attribute in the current tag token.
						# Set that attribute's name to the current input character, and its value to the empty string.

						static::state(RUDE_HTML_STATE_ATTRIBUTE_NAME);

						break;

					default:
						# Start a new attribute in the current tag token
						# Set that attribute's name and value to the empty string

						static::state_reconsume(RUDE_HTML_STATE_ATTRIBUTE_NAME);
				}

				break;

			# 8.2.4.33. Attribute name state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------------------------------------------------
			# U+0009 CHARACTER TABULATION (tab) |
			# U+000A LINE FEED (LF)             |
			# U+000C FORM FEED (FF)             |
			# U+0020 SPACE                      |
			# U+002F SOLIDUS (/)                |
			# U+003E GREATER-THAN SIGN (>)      |
			# EOF                               | Reconsume in the after attribute name state.
			# U+003D EQUALS SIGN (=)            | Switch to the before attribute value state.
			# Uppercase ASCII letter            | Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current attribute's name.
			# U+0000 NULL                       | Parse error. Append a U+FFFD REPLACEMENT CHARACTER character to the current attribute's name.
			# U+0022 QUOTATION MARK (")         |
			# U+0027 APOSTROPHE (')             |
			# U+003C LESS-THAN SIGN (<)         | Parse error. Treat it as per the "anything else" entry below.
			# Anything else                     | Append the current input character to the current attribute's name.

			case RUDE_HTML_STATE_ATTRIBUTE_NAME:

				static::char_consume();

				switch ($this->char)
				{
					case RUDE_HTML_CHAR_TAB:
					case RUDE_HTML_CHAR_LINE_FEED:
					case RUDE_HTML_CHAR_FORM_FEED:
					case RUDE_HTML_CHAR_SPACE:
					case RUDE_HTML_CHAR_EOF:
					case '/':
					case '>':
						static::state_reconsume(RUDE_HTML_STATE_AFTER_ATTRIBUTE_NAME);
						break;

					case '=':
						static::state(RUDE_HTML_STATE_BEFORE_ATTRIBUTE_VALUE);
						break;

					case RUDE_HTML_CHAR_NULL:
						static::parse_error();

						# Append a U+FFFD REPLACEMENT CHARACTER character to the current attribute's name.
						break;

					case '<':
					case '"':
					case "'":
						static::parse_error();

						# Parse error.
						# Append the current input character to the current attribute's name.

						break;

					default:

						if (static::ascii_is_uppercase())
						{
							# Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current attribute's name.
						}
						else
						{
							# Append the current input character to the current attribute's name.
						}
				}

				break;

			# 8.2.4.34. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.35. Before attribute value state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------------------------------------------------
			# U+0009 CHARACTER TABULATION (tab)
			# U+000A LINE FEED (LF)
			# U+000C FORM FEED (FF)
			# U+0020 SPACE                     Ignore the character.
			# U+0022 QUOTATION MARK (")        Switch to the attribute value (double-quoted) state.
			# U+0027 APOSTROPHE (')            Switch to the attribute value (single-quoted) state.
			# U+003E GREATER-THAN SIGN (>)     Parse error. Treat it as per the "anything else" entry below.
			# Anything else                    Reconsume in the attribute value (unquoted) state.

			case RUDE_HTML_STATE_BEFORE_ATTRIBUTE_VALUE:

				static::char_consume();

				switch ($this->char)
				{
					case RUDE_HTML_CHAR_TAB:
					case RUDE_HTML_CHAR_LINE_FEED:
					case RUDE_HTML_CHAR_FORM_FEED:
					case RUDE_HTML_CHAR_SPACE:
						# Ignore the character
						break;

					case '"':
						static::state_reconsume(RUDE_HTML_STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED);
						break;

					case "'":
						static::state_reconsume(RUDE_HTML_STATE_ATTRIBUTE_VALUE_SINGLE_QUOTED);
						break;

					case '>':
						static::parse_error();
						static::state_reconsume(RUDE_HTML_STATE_ATTRIBUTE_VALUE_UNQUOTED);
						break;

					default:
						static::state_reconsume(RUDE_HTML_STATE_ATTRIBUTE_VALUE_UNQUOTED);
				}

				break;

			# 8.2.4.36. Attribute value (double-quoted) state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------
			# U+0022 QUOTATION MARK (") Switch to the after attribute value (quoted) state.
			# U+0026 AMPERSAND (&)      Set the return state to the attribute value (double-quoted) state. Switch to the character reference state.
			# U+0000 NULL               Parse error. Append a U+FFFD REPLACEMENT CHARACTER character to the current attribute's value.
			# EOF                       Parse error. Emit an end-of-file token.
			# Anything else             Append the current input character to the current attribute's value.

			case RUDE_HTML_STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED:

				static::char_consume();

				switch ($this->char)
				{
					case '"': static::state(RUDE_HTML_STATE_AFTER_ATTRIBUTE_VALUE_QUOTED); break;
					case '&': static::state(RUDE_HTML_STATE_CHARACTER_REFERENCE, RUDE_HTML_STATE_ATTRIBUTE_VALUE_DOUBLE_QUOTED); break;

					case RUDE_HTML_CHAR_NULL:
						static::parse_error();
						# Append a U+FFFD REPLACEMENT CHARACTER character to the current attribute's value
						break;

					case RUDE_HTML_CHAR_EOF:
						static::parse_error();
						static::create_token_eof();
						break;

					default:
						# Append the current input character to the current attribute's value.
				}

				break;

			# 8.2.4.37. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.38. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.39. After attribute value (quoted) state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------
			# U+0009 CHARACTER TABULATION (tab) |
			# U+000A LINE FEED (LF)             |
			# U+000C FORM FEED (FF)             |
			# U+0020 SPACE                      | Switch to the before attribute name state.
			# U+002F SOLIDUS (/)                | Switch to the self-closing start tag state.
			# U+003E GREATER-THAN SIGN (>)      | Switch to the data state. Emit the current tag token.
			# EOF                               | Parse error. Emit an end-of-file token.
			# Anything else                     | Parse error. Reconsume in the before attribute name state.

			case RUDE_HTML_STATE_AFTER_ATTRIBUTE_VALUE_QUOTED:

				static::char_consume();

				switch ($this->char)
				{
					case RUDE_HTML_CHAR_TAB:
					case RUDE_HTML_CHAR_LINE_FEED:
					case RUDE_HTML_CHAR_FORM_FEED:
					case RUDE_HTML_CHAR_SPACE:
						static::state(RUDE_HTML_STATE_BEFORE_ATTRIBUTE_NAME);
						break;

					case '/':
						static::state(RUDE_HTML_STATE_SELF_CLOSING_START_TAG);
						break;

					case '>':
						static::state(RUDE_HTML_STATE_DATA);
						static::emit_char_current();
						break;

					case RUDE_HTML_CHAR_EOF:
						static::parse_error();
						static::create_token_eof();
						break;

					default:
						static::parse_error();
						static::state_reconsume(RUDE_HTML_STATE_ATTRIBUTE_NAME);
				}

				break;

			# 8.2.4.40. Self-closing start tag state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------
			# U+003E GREATER-THAN SIGN (>) | Set the self-closing flag of the current tag token. Switch to the data state. Emit the current tag token.
			# EOF                          | Parse error. Emit an end-of-file token.
			# Anything else                | Parse error. Reconsume in the before attribute name state.

			case RUDE_HTML_STATE_SELF_CLOSING_START_TAG:

				static::char_consume();

				switch ($this->chars)
				{
					case '>':
						$this->tokens->token->flags['self-closing'] = true;
						$this->tokens->emit();

						static::state(RUDE_HTML_STATE_DATA);
						break;

					case RUDE_HTML_CHAR_EOF:
						static::parse_error();

						$this->tokens->emit_eof();
						break;

					default:
						static::parse_error();

						static::state_reconsume(RUDE_HTML_STATE_ATTRIBUTE_NAME);
				}

				break;

			# 8.2.4.41. Bogus comment state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------
			# U+003E GREATER-THAN SIGN (>) | Switch to the data state. Emit the comment token.
			# EOF Emit the comment.        | Emit an end-of-file token.
			# U+0000 NULL                  | Append a U+FFFD REPLACEMENT CHARACTER character to the comment token's data.
			# Anything else                | Append the current input character to the comment token's data.

			case RUDE_HTML_STATE_BOGUS_COMMENT:

				static::char_consume();

				switch ($this->char)
				{
					case '>':
						$this->tokens->emit_comment();

						static::state(RUDE_HTML_STATE_DATA);
						break;

					case RUDE_HTML_CHAR_EOF:
						$this->tokens->emit_eof();
						break;

					case RUDE_HTML_CHAR_NULL:
						$this->tokens->token->comment .= RUDE_HTML_CHAR_REPLACEMENT;
						break;

					default:
						$this->tokens->token->comment .= $this->char;
				}

				break;

			# 8.2.4.42. Markup declaration open state
			#
			# If the next two characters are both U+002D HYPHEN-MINUS characters (-), consume those two characters, create a comment token whose data is the empty string, and switch to the comment start state.
			# Otherwise, if the next seven characters are an ASCII case-insensitive match for the word "DOCTYPE", then consume those characters and switch to the DOCTYPE state.
			# Otherwise, if there is an adjusted current node and it is not an element in the HTML namespace and the next seven characters are a case-sensitive match for the string "[CDATA[" (the five uppercase letters "CDATA" with a U+005B LEFT SQUARE BRACKET character before and after), then consume those characters and switch to the CDATA section state.
			# Otherwise, this is a parse error. Create a comment token whose data is the empty string. Switch to the bogus comment state (don't consume anything in the current state).

			case RUDE_HTML_STATE_MARKUP_DECLARATION_OPEN:

				if (static::is_next('--', 2))
				{
					static::chars_consume(2);

					$this->tokens->create('comment');
					$this->tokens->token->data = '';

					static::state(RUDE_HTML_STATE_COMMENT_START);
				}
				else if (static::is_next('DOCTYPE', 7))
				{
					static::chars_consume(7);
					static::state(RUDE_HTML_STATE_DOCTYPE);
				}
				else if (static::is_next('[CDATA[', 7, true))
				{
					static::chars_consume(7);
					static::state(RUDE_HTML_STATE_CDATA_SECTION);
				}
				else
				{
					static::parse_error();

					$this->token = static::token_create('comment');
					$this->token->comment;

					static::state(RUDE_HTML_STATE_BOGUS_COMMENT);
				}

				break;

			# 8.2.4.43. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.44. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.45. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.46. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.47. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.48. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.49. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.50. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.51. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.52. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			# 8.2.4.53. DOCTYPE state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------------------------------------------------
			# U+0009 CHARACTER TABULATION (tab) |
			# U+000A LINE FEED (LF)             |
			# U+000C FORM FEED (FF)             |
			# U+0020 SPACE                      | Switch to the before DOCTYPE name state.
			# EOF                               | Parse error. Create a new DOCTYPE token. Set its force-quirks flag to on. Emit the token. Emit an end-of-file token.
			# Anything else                     | Parse error. Reconsume in the before DOCTYPE name state.

			case RUDE_HTML_STATE_DOCTYPE:

				static::char_consume();

				switch ($this->char)
				{
					case RUDE_HTML_CHAR_TAB:
					case RUDE_HTML_CHAR_LINE_FEED:
					case RUDE_HTML_CHAR_FORM_FEED:
					case RUDE_HTML_CHAR_SPACE:
						static::state(RUDE_HTML_STATE_BEFORE_DOCTYPE_NAME);
						break;

					case RUDE_HTML_CHAR_EOF:
						static::parse_error();

						# Create a new DOCTYPE token
						# Set its force-quirks flag to on
						# Emit the token
						# Emit an end-of-file token

						break;

					default:
						static::parse_error();
						static::state_reconsume(RUDE_HTML_STATE_DOCTYPE_NAME);
				}

				break;

			# 8.2.4.54. Before DOCTYPE name state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------------------------------------------------
			# U+0009 CHARACTER TABULATION (tab) |
			# U+000A LINE FEED (LF)             |
			# U+000C FORM FEED (FF)             |
			# U+0020 SPACE                      | Ignore the character.
			# Uppercase ASCII letter            | Create a new DOCTYPE token. Set the token's name to the lowercase version of the current input character (add 0x0020 to the character's code point). Switch to the DOCTYPE name state.
			# U+0000 NULL                       | Parse error. Create a new DOCTYPE token. Set the token's name to a U+FFFD REPLACEMENT CHARACTER character. Switch to the DOCTYPE name state.
			# U+003E GREATER-THAN SIGN (>)      | Parse error. Create a new DOCTYPE token. Set its force-quirks flag to on. Switch to the data state. Emit the token.
			# EOF                               | Parse error. Create a new DOCTYPE token. Set its force-quirks flag to on. Emit the token. Emit an end-of-file token.
			# Anything else                     | Create a new DOCTYPE token. Set the token's name to the current input character. Switch to the DOCTYPE name state.

			case RUDE_HTML_STATE_BEFORE_DOCTYPE_NAME:

				static::char_consume();

				switch ($this->char)
				{
					case RUDE_HTML_CHAR_TAB:
					case RUDE_HTML_CHAR_LINE_FEED:
					case RUDE_HTML_CHAR_FORM_FEED:
					case RUDE_HTML_CHAR_SPACE:
						break;

					case RUDE_HTML_CHAR_NULL:
						static::parse_error();

						$this->tokens->create('DOCTYPE');
						$this->tokens->token->name = RUDE_HTML_CHAR_REPLACEMENT;

						static::state(RUDE_HTML_STATE_DOCTYPE_NAME);
						break;

					case '>':

						static::parse_error();

						$this->tokens->create('DOCTYPE');
						$this->tokens->token->flags['force-quirks'] = true;
						$this->tokens->emit();

						static::state(RUDE_HTML_STATE_DATA);
						break;

					case RUDE_HTML_CHAR_EOF:

						static::parse_error();

						$this->tokens->create('DOCTYPE');
						$this->tokens->token->flags['force-quirks'] = true;
						$this->tokens->emit();
						$this->tokens->emit_eof();
						break;

					default:
						$this->tokens->create('DOCTYPE');
						$this->tokens->token->name = $this->ascii->to_lowercase($this->char);

						static::state(RUDE_HTML_STATE_DOCTYPE_NAME);
				}

				break;

			# 8.2.4.55. DOCTYPE name state
			#
			# Consume the next input character:
			# ---------------------------------------------------------------------------------------------------------------------------------------
			# U+0009 CHARACTER TABULATION (tab) |
			# U+000A LINE FEED (LF)             |
			# U+000C FORM FEED (FF)             |
			# U+0020 SPACE                      | Switch to the after DOCTYPE name state.
			# U+003E GREATER-THAN SIGN (>)      | Switch to the data state. Emit the current DOCTYPE token.
			# Uppercase ASCII letter            | Append the lowercase version of the current input character (add 0x0020 to the character's code point) to the current DOCTYPE token's name.
			# U+0000 NULL                       | Parse error. Append a U+FFFD REPLACEMENT CHARACTER character to the current DOCTYPE token's name.
			# EOF                               | Parse error. Set the DOCTYPE token's force-quirks flag to on. Emit that DOCTYPE token. Emit an end-of-file token.
			# Anything else                     | Append the current input character to the current DOCTYPE token's name.

			case RUDE_HTML_STATE_DOCTYPE_NAME:

				static::char_consume();

				switch ($this->char)
				{
					case RUDE_HTML_CHAR_TAB:
					case RUDE_HTML_CHAR_LINE_FEED:
					case RUDE_HTML_CHAR_FORM_FEED:
					case RUDE_HTML_CHAR_SPACE:
						static::state(RUDE_HTML_STATE_AFTER_DOCTYPE_NAME);
						break;

					case '>':
						$this->tokens->token->name .= RUDE_HTML_CHAR_REPLACEMENT;
						$this->tokens->emit();

						static::state(RUDE_HTML_STATE_DATA);
						break;

					case RUDE_HTML_CHAR_NULL:
						static::parse_error();

						$this->tokens->token->name .= RUDE_HTML_CHAR_REPLACEMENT;
						break;

					case RUDE_HTML_CHAR_EOF:
						$this->tokens->token->flags['force-quirks'] = true;
						$this->tokens->emit();
						$this->tokens->emit_eof();
						break;

					default:
						$this->tokens->token->name .= $this->ascii->to_lowercase($this->char);
				}

				break;

			# 8.2.4.56. %%%%%% state
			#
			# Consume the next input character:
			# --------------------------------------------------------------------------------------------------------------

			default:

				exception::error("unknown state: $this->state");

				break;
		}
	}

	private function is_next($substring, $length = null, $case_insensetive = false)
	{
		if ($length === null)
		{
			$length = strlen($substring);
		}

		$limit = $this->offset + $length;

		if (!isset($this->chars[$limit]))
		{
			return false;
		}

		$string = '';

		for ($i = $this->offset; $i < $limit; $i++)
		{
			$string .= $this->chars[$i];
		}

		if ($case_insensetive === false)
		{
			return strcasecmp($string, $substring) === 0;
		}

		return strcmp($string, $substring) === 0;
	}

	private function char_consume()
	{
		$this->char = $this->chars[$this->offset];

		debug($this->char, true);

		$this->offset++;
	}

	private function chars_consume($chars)
	{
		for ($i = 0; $i < $chars; $i++)
		{
			static::char_consume();
		}
	}

	private function char_reconsume()
	{
		$this->offset--;
	}

	private function create_token_eof()         { static::token_create('EOF');                      }
	private function emit_char_solidus()        { static::emit_char(RUDE_HTML_CHAR_SOLIDUS);        }
	private function emit_char_replacement()    { static::emit_char(RUDE_HTML_CHAR_REPLACEMENT);    }
	private function emit_char_less_than_sign() { static::emit_char(RUDE_HTML_CHAR_LESS_THAN_SIGN); }

	private function emit_tag() { }

	private function emit_char_current() { static::emit_char($this->char); }

	private function emit_char($char)
	{
		debug($char, true);
	}

	private function create_tag_start()
	{
		console::log('tag opened', RUDE_E_SUCCESS);
		debug('<');
	}

	private function create_tag_end()
	{
		console::log('tag closed', RUDE_E_SUCCESS);
		debug('>');
	}

	private function create_comment()
	{
		debug('*comment*');
	}

	private function state_reconsume($state)
	{
		static::char_reconsume();
		static::state($state);
	}

	private function state($state, $state_return = null)
	{
		$this->state = $state;

		if ($state_return !== null)
		{
			static::state_return($state_return);
		}
	}

	private function state_return($value)
	{
		$this->state_return = $value;
	}

	private function parse_error()
	{
		exception::warning('parse error');
	}
}


text:
<?php

require_once(DIR_INC . 'classes/api/response_error.class.php');
require_once(DIR_INC . 'classes/api/responses.class.php');

class RErr_Need_Login extends Response_Error {
    public static $tag = 'NOT_LOGGED_IN';

    function __construct() {
        $this->set_response_code(Rest_Responses::$errors[self::$tag]);
        $this->set_payload('Not logged in');
    }

}


text:
PANEL = 'datasources'
PANEL_DASHBOARD = 'admin'
PANEL_GROUP = 'policy'
DASH_BOARDS = 'openstack_dashboard.dashboards'
ADD_PANEL = DASH_BOARDS + '.admin.datasources.panel.DataSources'


text:
module Mongoid::Commentable
  extend ActiveSupport::Concern
  included do |base|
    base.embeds_many :comments, :as => :commentable
    if  Gem::Version.new(Mongoid::VERSION) < Gem::Version.new('3.0.0')
      base.index [['comments', Mongo::ASCENDING]]
    else
      base.index 'comments' => 1
    end
  end

  module ClassMethods

    def commentable?
      true
    end
  end

  def create_comment!(params)
    comment = comments.create!(params)
    comment.path = comment.parent ? comments.find(comment.parent).path + '.' + comment.id.to_s : "root."+comment.id.to_s
    comment
  end

  def comments_list(sort=:asc)
    if Comment.respond_to?(sort)
      comments.send(sort,:path)
    else
      raise ArgumentError, "Wrong argument!"
    end
  end

  def branch_for(comment_id)
    comments.select{|i| i.path =~ Regexp.new('^' + comments.find(comment_id).path)}
  end

end


text:
namespace switches {

// Clears the token service before using it. This allows simulating the
// expiration of credentials during testing.
const char kClearTokenService[] = "clear-token-service";

// Disables consistent identity features.
const char kDisableAccountConsistency[] = "disable-account-consistency";

// Disables new profile management system, including new profile chooser UI.
const char kDisableNewProfileManagement[] = "disable-new-profile-management";

// Disables sending signin scoped device id to LSO with refresh token request.
const char kDisableSigninScopedDeviceId[] = "disable-signin-scoped-device-id";

// Enables consistent identity features.
const char kEnableAccountConsistency[] = "enable-account-consistency";

// Enables new profile management system, including lock mode.
const char kEnableNewProfileManagement[] = "new-profile-management";

// Enables sending EnableRefreshTokenAnnotationRequest.
extern const char kEnableRefreshTokenAnnotationRequest[] =
    "enable-refresh-token-annotation-request";

// Enables multiple account versions of chrome.identity APIs.
const char kExtensionsMultiAccount[] = "extensions-multi-account";

// Enables using GAIA information to populate profile name and icon.
const char kGoogleProfileInfo[] = "google-profile-info";

const base::Feature kMaterialDesignUserManager {
  "MaterialDesignUserManager", base::FEATURE_DISABLED_BY_DEFAULT
};

// Enables or disables the new password separated sign in flow in a tab modal
// dialog.
const base::Feature kUsePasswordSeparatedSigninFlow {
  "UsePasswordSeparatedSigninFlow", base::FEATURE_DISABLED_BY_DEFAULT
};

}  // namespace switches


text:
/**
 * Implementation of the device driver management subsystem.
 */
package org.onosproject.net.driver.impl;


text:
layout: post
title: eod-wednesday-at-devconnections
---
Today the session quality was "iffy".  I wound up leaving a few early,
normally because the presenter named his or her session poorly.  Please
people if you are going to be presenting on a topic name your
presentations correctly.  If you are going to be showing an overview of
a technology, don't call it "Developing with Technology X" call it an
overview.  Please don't name your sessions things like "Indigo says Hi!"
or "You, ASP.NET and Me".  WTF?  How am I supposed to figure out what
that session is about?  It might be great, or it might be boring.  My
work spent good money to get me out here, and I'm not going to take a
stab in the dark.  If I can't figure out what the session is, I'm not
going.  Simple.

On another note, the people in charge seem to realize that giving 3000
people 30 minutes to travel a half a mile to the expo area and back for
a break is braindead.  They moved the refreshments this afternoon to the
hallway outside the sessions.  Good move!

This evening I'm going out for a little night on the town.  I'll
probably start with some craps at Mandalay, but later on I'm going to
see Avenue Q with my buddy Richard (who also was able to con work into
sending him out here).

Technorati Tags :
[DevConnections](http://technorati.com/tag/DevConnections)


text:
package com.microsoft.azure.management.kusto.v2018_09_07_preview;

import java.util.Collection;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.microsoft.rest.ExpandableStringEnum;

/**
 * Defines values for DatabasePrincipalRole.
 */
public final class DatabasePrincipalRole extends ExpandableStringEnum<DatabasePrincipalRole> {
    /** Static value Admin for DatabasePrincipalRole. */
    public static final DatabasePrincipalRole ADMIN = fromString("Admin");

    /** Static value Ingestor for DatabasePrincipalRole. */
    public static final DatabasePrincipalRole INGESTOR = fromString("Ingestor");

    /** Static value Monitor for DatabasePrincipalRole. */
    public static final DatabasePrincipalRole MONITOR = fromString("Monitor");

    /** Static value User for DatabasePrincipalRole. */
    public static final DatabasePrincipalRole USER = fromString("User");

    /** Static value UnrestrictedViewers for DatabasePrincipalRole. */
    public static final DatabasePrincipalRole UNRESTRICTED_VIEWERS = fromString("UnrestrictedViewers");

    /** Static value Viewer for DatabasePrincipalRole. */
    public static final DatabasePrincipalRole VIEWER = fromString("Viewer");

    /**
     * Creates or finds a DatabasePrincipalRole from its string representation.
     * @param name a name to look for
     * @return the corresponding DatabasePrincipalRole
     */
    @JsonCreator
    public static DatabasePrincipalRole fromString(String name) {
        return fromString(name, DatabasePrincipalRole.class);
    }

    /**
     * @return known DatabasePrincipalRole values
     */
    public static Collection<DatabasePrincipalRole> values() {
        return values(DatabasePrincipalRole.class);
    }
}


text:
"""
Ramsey numbers.
"""
#   Copyright (C) 2011 by
#   Nicholas Mancuso <nick.mancuso@gmail.com>
#   All rights reserved.
#   BSD license.
import networkx as nx
from ...utils import arbitrary_element

__all__ = ["ramsey_R2"]
__author__ = """Nicholas Mancuso (nick.mancuso@gmail.com)"""

def ramsey_R2(G):
    r"""Approximately computes the Ramsey number `R(2;s,t)` for graph.

    Parameters
    ----------
    G : NetworkX graph
        Undirected graph

    Returns
    -------
    max_pair : (set, set) tuple
        Maximum clique, Maximum independent set.
    """
    if not G:
        return set(), set()

    node = arbitrary_element(G)
    nbrs = nx.all_neighbors(G, node)
    nnbrs = nx.non_neighbors(G, node)
    c_1, i_1 = ramsey_R2(G.subgraph(nbrs))
    c_2, i_2 = ramsey_R2(G.subgraph(nnbrs))

    c_1.add(node)
    i_2.add(node)
    # Choose the larger of the two cliques and the larger of the two
    # independent sets, according to cardinality.
    return max(c_1, c_2, key=len), max(i_1, i_2, key=len)


text:
- __CommonServerPython__
  - Added **Endpoint** Common class.


text:
package loon.geom;

import loon.LRelease;

public class LongValue implements LRelease{

	private long value;

	public LongValue() {
		this(0);
	}

	public LongValue(long v) {
		this.set(v);
	}

	public LongValue set(long v) {
		this.value = v;
		return this;
	}

	public long get() {
		return result();
	}

	public long result() {
		return value;
	}

	@Override
	public String toString() {
		return String.valueOf(value);
	}

	@Override
	public void close() {
		this.value = 0;
	}

}


text:
/**
 * \file
 * \brief Null implementation of plat_advance_aps
 */

/*
 * Copyright (c) 2016 ETH Zurich.
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
 */

#include <kernel.h>

#include <boot_protocol.h>

/* Many platforms don't need any help to get the boot driver up. */
void
plat_advance_aps(void) {
}


text:
#ifndef _IDASLS_IMPL_H
#define _IDASLS_IMPL_H

#include <idas/idas_ls.h>
#include "idas_impl.h"

#ifdef __cplusplus  /* wrapper to enable C++ usage */
extern "C" {
#endif

/*-----------------------------------------------------------------
  Types : struct IDALsMemRec, struct *IDALsMem

  The type IDALsMem is a pointer to a IDALsMemRec, which is a
  structure containing fields that must be accessible by LS module
  routines.
  -----------------------------------------------------------------*/
typedef struct IDALsMemRec {

  /* Linear solver type information */
  booleantype iterative;    /* is the solver iterative?    */
  booleantype matrixbased;  /* is a matrix structure used? */

  /* Jacobian construction & storage */
  booleantype jacDQ;    /* SUNTRUE if using internal DQ Jacobian approx. */
  IDALsJacFn jac;       /* Jacobian routine to be called                 */
  void *J_data;         /* J_data is passed to jac                       */

  /* Linear solver, matrix and vector objects/pointers */
  SUNLinearSolver LS;   /* generic linear solver object                  */
  SUNMatrix J;          /* J = dF/dy + cj*dF/dy'                         */
  N_Vector ytemp;       /* temp vector used by IDAAtimesDQ               */
  N_Vector yptemp;      /* temp vector used by IDAAtimesDQ               */
  N_Vector x;           /* temp vector used by the solve function        */
  N_Vector ycur;        /* current y vector in Newton iteration          */
  N_Vector ypcur;       /* current yp vector in Newton iteration         */
  N_Vector rcur;        /* rcur = F(tn, ycur, ypcur)                     */

  /* Matrix-based solver, scale solution to account for change in cj */
  booleantype scalesol;

  /* Iterative solver tolerance */
  realtype eplifac;   /* nonlinear -> linear tol scaling factor       */
  realtype nrmfac;    /* integrator -> LS norm conversion factor      */

  /* Statistics and associated parameters */
  realtype dqincfac;  /* dqincfac = optional increment factor in Jv   */
  long int nje;       /* nje = no. of calls to jac                    */
  long int npe;       /* npe = total number of precond calls          */
  long int nli;       /* nli = total number of linear iterations      */
  long int nps;       /* nps = total number of psolve calls           */
  long int ncfl;      /* ncfl = total number of convergence failures  */
  long int nreDQ;     /* nreDQ = total number of calls to res         */
  long int njtsetup;  /* njtsetup = total number of calls to jtsetup  */
  long int njtimes;   /* njtimes = total number of calls to jtimes    */
  long int nst0;      /* nst0 = saved nst (for performance monitor)   */
  long int nni0;      /* nni0 = saved nni (for performance monitor)   */
  long int ncfn0;     /* ncfn0 = saved ncfn (for performance monitor) */
  long int ncfl0;     /* ncfl0 = saved ncfl (for performance monitor) */
  long int nwarn;     /* nwarn = no. of warnings (for perf. monitor)  */

  int last_flag;      /* last error return flag                       */

  /* Preconditioner computation
     (a) user-provided:
         - pdata == user_data
         - pfree == NULL (the user dealocates memory)
     (b) internal preconditioner module
         - pdata == ida_mem
         - pfree == set by the prec. module and called in idaLsFree */
  IDALsPrecSetupFn pset;
  IDALsPrecSolveFn psolve;
  int (*pfree)(IDAMem IDA_mem);
  void *pdata;

  /* Jacobian times vector compuation
     (a) jtimes function provided by the user:
         - jt_data == user_data
         - jtimesDQ == SUNFALSE
     (b) internal jtimes
         - jt_data == ida_mem
         - jtimesDQ == SUNTRUE */
  booleantype jtimesDQ;
  IDALsJacTimesSetupFn jtsetup;
  IDALsJacTimesVecFn jtimes;
  IDAResFn jt_res;
  void *jt_data;

} *IDALsMem;

/*-----------------------------------------------------------------
  Prototypes of internal functions
  -----------------------------------------------------------------*/

/* Interface routines called by system SUNLinearSolver */
int idaLsATimes(void *ida_mem, N_Vector v, N_Vector z);
int idaLsPSetup(void *ida_mem);
int idaLsPSolve(void *ida_mem, N_Vector r, N_Vector z,
                realtype tol, int lr);

/* Difference quotient approximation for Jac times vector */
int idaLsDQJtimes(realtype tt, N_Vector yy, N_Vector yp,
                  N_Vector rr, N_Vector v, N_Vector Jv,
                  realtype c_j, void *data,
                  N_Vector work1, N_Vector work2);

/* Difference-quotient Jacobian approximation routines */
int idaLsDQJac(realtype tt, realtype c_j, N_Vector yy, N_Vector yp,
               N_Vector rr, SUNMatrix Jac, void *data,
               N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
int idaLsDenseDQJac(realtype tt, realtype c_j, N_Vector yy,
                    N_Vector yp, N_Vector rr, SUNMatrix Jac,
                    IDAMem IDA_mem, N_Vector tmp1);
int idaLsBandDQJac(realtype tt, realtype c_j,  N_Vector yy,
                   N_Vector yp, N_Vector rr, SUNMatrix Jac,
                   IDAMem IDA_mem, N_Vector tmp1,
                   N_Vector tmp2, N_Vector tmp3);

/* Generic linit/lsetup/lsolve/lperf/lfree interface routines for IDA to call */
int idaLsInitialize(IDAMem IDA_mem);
int idaLsSetup(IDAMem IDA_mem, N_Vector y, N_Vector yp, N_Vector r,
               N_Vector vt1, N_Vector vt2, N_Vector vt3);
int idaLsSolve(IDAMem IDA_mem, N_Vector b, N_Vector weight,
               N_Vector ycur, N_Vector ypcur, N_Vector rescur);
int idaLsPerf(IDAMem IDA_mem, int perftask);
int idaLsFree(IDAMem IDA_mem);

/* Auxilliary functions */
int idaLsInitializeCounters(IDALsMem idals_mem);
int idaLs_AccessLMem(void* ida_mem, const char* fname,
                     IDAMem* IDA_mem, IDALsMem* idals_mem);

/*---------------------------------------------------------------
  Error and Warning Messages
  ---------------------------------------------------------------*/

#if defined(SUNDIALS_EXTENDED_PRECISION)
#define MSG_LS_TIME "at t = %Lg, "
#define MSG_LS_FRMT "%Le."
#elif defined(SUNDIALS_DOUBLE_PRECISION)
#define MSG_LS_TIME "at t = %lg, "
#define MSG_LS_FRMT "%le."
#else
#define MSG_LS_TIME "at t = %g, "
#define MSG_LS_FRMT "%e."
#endif

/* Error Messages */
#define MSG_LS_IDAMEM_NULL    "Integrator memory is NULL."
#define MSG_LS_MEM_FAIL       "A memory request failed."
#define MSG_LS_BAD_NVECTOR    "A required vector operation is not implemented."
#define MSG_LS_BAD_SIZES      "Illegal bandwidth parameter(s). Must have 0 <=  ml, mu <= N-1."
#define MSG_LS_BAD_LSTYPE     "Incompatible linear solver type."
#define MSG_LS_LMEM_NULL      "Linear solver memory is NULL."
#define MSG_LS_BAD_GSTYPE     "gstype has an illegal value."
#define MSG_LS_NEG_MAXRS      "maxrs < 0 illegal."
#define MSG_LS_NEG_EPLIFAC    "eplifac < 0.0 illegal."
#define MSG_LS_NEG_DQINCFAC   "dqincfac < 0.0 illegal."
#define MSG_LS_PSET_FAILED    "The preconditioner setup routine failed in an unrecoverable manner."
#define MSG_LS_PSOLVE_FAILED  "The preconditioner solve routine failed in an unrecoverable manner."
#define MSG_LS_JTSETUP_FAILED "The Jacobian x vector setup routine failed in an unrecoverable manner."
#define MSG_LS_JTIMES_FAILED  "The Jacobian x vector routine failed in an unrecoverable manner."
#define MSG_LS_JACFUNC_FAILED "The Jacobian routine failed in an unrecoverable manner."
#define MSG_LS_MATZERO_FAILED "The SUNMatZero routine failed in an unrecoverable manner."

/* Warning Messages */
#define MSG_LS_WARN  "Warning: " MSG_LS_TIME "poor iterative algorithm performance. "
#define MSG_LS_CFN_WARN  MSG_LS_WARN "Nonlinear convergence failure rate is " MSG_LS_FRMT
#define MSG_LS_CFL_WARN  MSG_LS_WARN "Linear convergence failure rate is " MSG_LS_FRMT

/*-----------------------------------------------------------------
  PART II - backward problems
  -----------------------------------------------------------------*/

/*-----------------------------------------------------------------
  Types : IDALsMemRecB, IDALsMemB

  IDASetLinearSolverB attaches such a structure to the lmemB
  field of IDAadjMem
  -----------------------------------------------------------------*/
typedef struct IDALsMemRecB {

  IDALsJacFnB            jacB;
  IDALsJacFnBS           jacBS;
  IDALsJacTimesSetupFnB  jtsetupB;
  IDALsJacTimesSetupFnBS jtsetupBS;
  IDALsJacTimesVecFnB    jtimesB;
  IDALsJacTimesVecFnBS   jtimesBS;
  IDALsPrecSetupFnB      psetB;
  IDALsPrecSetupFnBS     psetBS;
  IDALsPrecSolveFnB      psolveB;
  IDALsPrecSolveFnBS     psolveBS;
  void                  *P_dataB;

} *IDALsMemB;

/*-----------------------------------------------------------------
  Prototypes of internal functions
  -----------------------------------------------------------------*/

int idaLsFreeB(IDABMem IDAB_mem);
int idaLs_AccessLMemB(void *ida_mem, int which, const char *fname,
                      IDAMem *IDA_mem, IDAadjMem *IDAADJ_mem,
                      IDABMem *IDAB_mem, IDALsMemB *idalsB_mem);
int idaLs_AccessLMemBCur(void *ida_mem, const char *fname,
                         IDAMem *IDA_mem, IDAadjMem *IDAADJ_mem,
                         IDABMem *IDAB_mem, IDALsMemB *idalsB_mem);

/*-----------------------------------------------------------------
  Error Messages
  -----------------------------------------------------------------*/
#define MSG_LS_CAMEM_NULL  "idaadj_mem = NULL illegal."
#define MSG_LS_LMEMB_NULL  "Linear solver memory is NULL for the backward integration."
#define MSG_LS_BAD_T       "Bad t for interpolation."
#define MSG_LS_BAD_WHICH   "Illegal value for which."
#define MSG_LS_NO_ADJ      "Illegal attempt to call before calling IDAAdjInit."

#ifdef __cplusplus
}
#endif

#endif


text:
module BeachApiCore
  class V1::ChatsController < BeachApiCore::V1::BaseController
    include ChatsDoc
    include BeachApiCore::Concerns::V1::ResourceConcern
    before_action :application_authorize!, only: %i(create add_recipient)
    before_action :authenticate_service_for_doorkeeper_application, only: [:create, :add_recipient]
    before_action :doorkeeper_authorize!, except: %i(create add_recipient)
    before_action :authenticate_service_for_application, except: [:create, :add_recipient]
    before_action :get_resource, only: %i(read add_recipient)

    resource_description do
      name I18n.t('activerecord.models.beach_api_core/chat.other')
      error code: 403, desc: I18n.t('api.resource_description.errors.forbidden_request')
      error code: 401, desc: I18n.t('api.resource_description.errors.unauthorized')
      error code: 400, desc: I18n.t('api.resource_description.errors.bad_request')
    end

    def index
      render_json_success(current_user.chats, :ok, root: :chats)
    end

    def create
      result = BeachApiCore::ChatCreate.call(user: current_user, keeper: keeper, params: chat_params)

      if result.success?
        render_json_success(result.chat, result.status, root: :chat, current_user: current_user)
      else
        render_json_error({ message: result.message }, result.status)
      end
    end

    def add_recipient
      authorize @chat
      result = BeachApiCore::ChatAddRecipient.call(recipient: recipient, chat: @chat)

      if result.success?
        render_json_success(result.chat, result.status, root: :chat, current_user: current_user)
      else
        render_json_error({ message: result.message }, result.status)
      end
    end

    def read
      authorize @chat
      result = BeachApiCore::ChatRead.call(chat: @chat, user: current_user)

      if result.success?
        render_json_success(result.chat, result.status, root: :chat, current_user: current_user)
      else
        render_json_error({ message: result.chat }, result.status)
      end
    end

    private

    def chat_params
      return unless params[:chat]
      params.require(:chat).permit(chats_users_attributes: [:user_id])
    end

    def keeper
      current_user || current_application
    end

    def recipient
      User.find(params[:chat][:recipient_id])
    end
  end
end