text:
URL Management
==============

> Note: This section is under development.

The concept of URL management in Yii is fairly simple. URL management is based on the premise that the application uses
internal routes and parameters everywhere. The framework itself will then translate routes into URLs, and vice versa, according to the URL manager's configuration. This approach allows you to change site-wide URLs merely by
editing a single configuration file, without ever touching the application code.

Internal routes
---------------

When implementing an application using Yii, you'll deal with internal routes, often referred to as routes and parameters.
Each controller and controller action has a corresponding internal route such as `site/index` or `user/create`.
In the first example, `site` is referred to as the *controller ID* while `index` is referred to as the *action ID*. In the
second example, `user` is the controller ID and `create` is the action ID. If the controller belongs to a *module*, the
internal route is prefixed with the module ID. For example `blog/post/index` for a blog module (with `post` being the
controller ID and `index` being the action ID).

Creating URLs
-------------

The most important rule for creating URLs in your site is to always do so using the URL manager. The URL manager is a built-in application component named `urlManager`. This component is accessible from both web and console applications via
`\Yii::$app->urlManager`. The component makes available the two following URL creation methods:

- `createUrl($params)`
- `createAbsoluteUrl($params, $schema = null)`

The `createUrl` method creates an URL relative to the application root, such as `/index.php/site/index/`.
The `createAbsoluteUrl` method creates an URL prefixed with the proper protocol and hostname:
`http://www.example.com/index.php/site/index`. The former is suitable for internal application URLs, while the latter
is used when you need to create URLs for external resources, such as connecting to third party services, sending email,
generating RSS feeds etc.

Some examples:

```php
echo \Yii::$app->urlManager->createUrl(['site/page', 'id' => 'about']);
// /index.php/site/page/id/about/
echo \Yii::$app->urlManager->createUrl(['date-time/fast-forward', 'id' => 105])
// /index.php?r=date-time/fast-forward&id=105
echo \Yii::$app->urlManager->createAbsoluteUrl('blog/post/index');
// http://www.example.com/index.php/blog/post/index/
```

The exact format of the URL depends on how the URL manager is configured. The above
examples may also output:

* `/site/page/id/about/`
* `/index.php?r=site/page&id=about`
* `/index.php?r=date-time/fast-forward&id=105`
* `/index.php/date-time/fast-forward?id=105`
* `http://www.example.com/blog/post/index/`
* `http://www.example.com/index.php?r=blog/post/index`

In order to simplify URL creation there is [[yii\helpers\Url]] helper. Assuming we're at `/index.php?r=management/default/users&id=10` the following
is how `Url` helper works:

```php
use yii\helpers\Url;

// currently active route
// /index.php?r=management/default/users
echo Url::to('');

// same controller, different action
// /index.php?r=management/default/page&id=contact
echo Url::toRoute(['page', 'id' => 'contact']);

// same module, different controller and action
// /index.php?r=management/post/index
echo Url::toRoute('post/index');

// absolute route no matter what controller is making this call
// /index.php?r=site/index
echo Url::toRoute('/site/index');

// url for the case sensitive action `actionHiTech` of the current controller
// /index.php?r=management/default/hi-tech
echo Url::toRoute('hi-tech');

// url for action the case sensitive controller, `DateTimeController::actionFastForward`
// /index.php?r=date-time/fast-forward&id=105
echo Url::toRoute(['/date-time/fast-forward', 'id' => 105]);

// get URL from alias
// http://google.com/
Yii::setAlias('@google', 'http://google.com/');
echo Url::to('@google');

// get home URL
// /index.php?r=site/index
echo Url::home();

Url::remember(); // save URL to be used later
Url::previous(); // get previously saved URL
```

> **Tip**: In order to generate URL with a hashtag, for example `/index.php?r=site/page&id=100#title`, you need to
  specify the parameter named `#` using `Url::to(['post/read', 'id' => 100, '#' => 'title'])`.

There's also `Url::canonical()` method that allows you to generate
[canonical URL](https://en.wikipedia.org/wiki/Canonical_link_element) for the currently executing action.
The method ignores all action parameters except ones passed via action arguments:

```php
namespace app\controllers;

use yii\web\Controller;
use yii\helpers\Url;

class CanonicalController extends Controller
{
    public function actionTest($page)
    {
        echo Url::canonical();
    }
}
```

When accessed as `/index.php?r=canonical/test&page=hello&number=42` canonical URL will be `/index.php?r=canonical/test&page=hello`.

Customizing URLs
----------------

By default, Yii uses a query string format for URLs, such as `/index.php?r=news/view&id=100`. In order to make URLs
human-friendly i.e., more readable, you need to configure the `urlManager` component in the application's configuration
file. Enabling "pretty" URLs will convert the query string format to a directory-based format: `/index.php/news/view?id=100`.
Disabling the `showScriptName` parameter means that `index.php` will not be part of the URLs. Here's the relevant part of
the application's configuration file:

```php
<?php
return [
    // ...
    'components' => [
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
        ],
    ],
];
```

Note that this configuration will only work if the web server has been properly configured for Yii, see
[installation](installation.md#recommended-apache-configuration).

### Named parameters

A rule can be associated with a few `GET` parameters. These `GET` parameters appear in the rule's pattern as special tokens in the following format:

```
<ParameterName:ParameterPattern>
```

`ParameterName` is a name of a `GET` parameter, and the optional `ParameterPattern` is the regular expression that should
be used to match the value of the `GET` parameter. In case `ParameterPattern` is omitted, it means the parameter
should match any characters except `/`. When creating a URL, these parameter tokens will be replaced with the
corresponding parameter values; when parsing a URL, the corresponding GET parameters will be populated with the parsed results.

Let's use some examples to explain how URL rules work. We assume that our rule set consists of three rules:

```php
[
    'posts'=>'post/list',
    'post/<id:\d+>'=>'post/read',
    'post/<year:\d{4}>/<title>'=>'post/read',
]
```

- Calling `Url::toRoute('post/list')` generates `/index.php/posts`. The first rule is applied.
- Calling `Url::toRoute(['post/read', 'id' => 100])` generates `/index.php/post/100`. The second rule is applied.
- Calling `Url::toRoute(['post/read', 'year' => 2008, 'title' => 'a sample post'])` generates
  `/index.php/post/2008/a%20sample%20post`. The third rule is applied.
- Calling `Url::toRoute('post/read')` generates `/index.php/post/read`. None of the rules is applied, convention is used
  instead.

In summary, when using `createUrl` to generate a URL, the route and the `GET` parameters passed to the method are used to
decide which URL rule to be applied. If every parameter associated with a rule can be found in the `GET` parameters passed
to `createUrl`, and if the route of the rule also matches the route parameter, the rule will be used to generate the URL.

If the `GET` parameters passed to `Url::toRoute` are more than those required by a rule, the additional parameters will
appear in the query string. For example, if we call `Url::toRoute(['post/read', 'id' => 100, 'year' => 2008])`, we will
obtain `/index.php/post/100?year=2008`.

As we mentioned earlier, the other purpose of URL rules is to parse the requesting URLs. Naturally, this is an inverse
process of URL creation. For example, when a user requests for `/index.php/post/100`, the second rule in the above example
will apply, which resolves in the route `post/read` and the `GET` parameter `['id' => 100]` (accessible via
`Yii::$app->request->get('id')`).

### Parameterizing Routes

We may reference named parameters in the route part of a rule. This allows a rule to be applied to multiple routes based
on matching criteria. It may also help reduce the number of rules needed for an application, and thus improve the overall
performance.

We use the following example rules to illustrate how to parameterize routes with named parameters:

```php
[
    '<controller:(post|comment)>/<id:\d+>/<action:(create|update|delete)>' => '<controller>/<action>',
    '<controller:(post|comment)>/<id:\d+>' => '<controller>/read',
    '<controller:(post|comment)>s' => '<controller>/list',
]
```

In the above example, we use two named parameters in the route part of the rules: `controller` and `action`. The former matches a controller ID to be either post or comment, while the latter matches an action ID to be create, update or delete. You may name the parameters differently as long as they do not conflict with GET parameters that may appear in URLs.

Using the above rules, the URL `/index.php/post/123/create` will be parsed as the route `post/create` with `GET` parameter
`id=123`. Given the route `comment/list` and `GET` parameter `page=2`, we can create a URL `/index.php/comments?page=2`.

### Parameterizing  hostnames

It is also possible to include hostnames in the rules for parsing and creating URLs. One may extract part of the hostname
to be a `GET` parameter. This is especially useful for handling subdomains. For example, the URL
`http://admin.example.com/en/profile` may be parsed into GET parameters `user=admin` and `lang=en`. On the other hand,
rules with hostname may also be used to create URLs with parameterized hostnames.

In order to use parameterized hostnames, simply declare URL rules with host info, e.g.:

```php
[
    'http://<user:\w+>.example.com/<lang:\w+>/profile' => 'user/profile',
]
```

In the above example the first segment of the hostname is treated as the user parameter while the first segment
of the path info is treated as the lang parameter. The rule corresponds to the `user/profile` route.

Note that [[yii\web\UrlManager::showScriptName]] will not take effect when a URL is being created using a rule with a parameterized hostname.

Also note that any rule with a parameterized hostname should NOT contain the subfolder if the application is under
a subfolder of the Web root. For example, if the application is under `http://www.example.com/sandbox/blog`, then we
should still use the same URL rule as described above without the subfolder `sandbox/blog`.

### Faking URL Suffix

```php
<?php
return [
    // ...
    'components' => [
        'urlManager' => [
            'suffix' => '.html',
        ],
    ],
];
```

### Handling REST requests

TBD:
- RESTful routing: [[yii\filters\VerbFilter]], [[yii\web\UrlManager::$rules]]
- Json API:
  - response: [[yii\web\Response::format]]
  - request: [[yii\web\Request::$parsers]], [[yii\web\JsonParser]]

URL parsing
-----------

Complimentary to creating URLs Yii also handles transforming custom URLs back into internal routes and parameters.

### Strict URL parsing

By default if there's no custom rule for a URL and the URL matches the default format such as `/site/page`, Yii tries to run the corresponding controller's action. This behavior can be disabled so if there's no custom rule match, a 404 not found error will be produced immediately.

```php
<?php
return [
    // ...
    'components' => [
        'urlManager' => [
            'enableStrictParsing' => true,
        ],
    ],
];
```

Creating your own rule classes
------------------------------

[[yii\web\UrlRule]] class is used for both parsing URL into parameters and creating URL based on parameters. Despite
the fact that default implementation is flexible enough for the majority of projects, there are situations when using
your own rule class is the best choice. For example, in a car dealer website, we may want to support the URL format like
`/Manufacturer/Model`, where `Manufacturer` and `Model` must both match some data in a database table. The default rule
class will not work because it mostly relies on statically declared regular expressions which have no database knowledge.

We can write a new URL rule class by extending from [[yii\web\UrlRule]] and use it in one or multiple URL rules. Using
the above car dealer website as an example, we may declare the following URL rules in application config:

```php
// ...
'components' => [
    'urlManager' => [
        'rules' => [
            '<action:(login|logout|about)>' => 'site/<action>',

            // ...

            ['class' => 'app\components\CarUrlRule', 'connectionID' => 'db', /* ... */],
        ],
    ],
],
```

In the above, we use the custom URL rule class `CarUrlRule` to handle
the URL format `/Manufacturer/Model`. The class can be written like the following:

```php
namespace app\components;

use yii\web\UrlRule;

class CarUrlRule extends UrlRule
{
    public $connectionID = 'db';

    public function createUrl($manager, $route, $params)
    {
        if ($route === 'car/index') {
            if (isset($params['manufacturer'], $params['model'])) {
                return $params['manufacturer'] . '/' . $params['model'];
            } elseif (isset($params['manufacturer'])) {
                return $params['manufacturer'];
            }
        }
        return false;  // this rule does not apply
    }

    public function parseRequest($manager, $request)
    {
        $pathInfo = $request->getPathInfo();
        if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) {
            // check $matches[1] and $matches[3] to see
            // if they match a manufacturer and a model in the database
            // If so, set $params['manufacturer'] and/or $params['model']
            // and return ['car/index', $params]
        }
        return false;  // this rule does not apply
    }
}
```

Besides the above usage, custom URL rule classes can also be implemented
for many other purposes. For example, we can write a rule class to log the URL parsing
and creation requests. This may be useful during development stage. We can also
write a rule class to display a special 404 error page in case all other URL rules fail
to resolve the current request. Note that in this case, the rule of this special class
must be declared as the last rule.


text:
<?php

namespace php_websocket\models;

interface ModelInterface {
    /**
    * @param WebSocket $webSocket, instance of WebSocket class
    * @package php_websocket
    * MUST be implemented
    * To use the WebSocket method inside the models
    */
    public function addInstance(php_websocket\WebSocket $webSocket);

}

redpajama_set_name: RedPajamaGithub


text:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using ZombieSmashers.map;
using Microsoft.Xna.Framework.Net;
using ZombieSmashers.net;

namespace ZombieSmashers.Particles
{
    public class Particle
    {
        public const byte PARTICLE_NONE = 0;
        public const byte PARTICLE_BLOOD = 1;
        public const byte PARTICLE_BLOOD_DUST = 2;
        public const byte PARTICLE_BULLET = 3;
        public const byte PARTICLE_FIRE = 4;
        public const byte PARTICLE_FOG = 5;
        public const byte PARTICLE_HEAT = 6;
        public const byte PARTICLE_HIT = 7;
        public const byte PARTICLE_MUZZLEFLASH = 8;
        public const byte PARTICLE_ROCKET = 9;
        public const byte PARTICLE_SHOCKWAVE = 10;
        public const byte PARTICLE_SMOKE = 11;

        protected Vector2 Location;
        protected Vector2 Trajectory;

        protected float frame;
        protected float r, g, b, a;
        protected float size;
        protected float rotation;

        protected int flag;

        protected int owner;

        protected bool additive;

        public bool Exists;

        public bool Background;

        public bool refract;

        public bool netSendAndKill;
        public bool netSend;

        public Vector2 GetLoc()
        {
            return Location;
        }

        public Vector2 GetTraj()
        {
            return Trajectory;
        }

        public int GetFlag()
        {
            return flag;
        }

        public Vector2 GameLocation
        {
            get { return Location - Game1.Scroll; }
        }

        public bool Additive
        {
            get { return additive; }
            protected set { additive = value; }
        }

        public int Owner
        {
            get { return owner; }
            set { owner = value; }
        }

        public int Flag
        {
            get { return flag; }
        }

        public Particle()
        {
            Exists = false;
        }

        public virtual void Update(float gameTime,
            Map map,
            ParticleManager pMan,
            Character[] c)
        {
            Location += Trajectory * gameTime;
            frame -= gameTime;
            if (frame < 0.0f) KillMe();
        }

        public virtual void KillMe()
        {
            Exists = false;
        }

        public virtual void NetWrite(PacketWriter writer)
        {
            writer.Write(NetGame.MSG_PARTICLE);
            writer.Write(PARTICLE_NONE);
            writer.Write(Background);
        }

        public virtual void Draw(SpriteBatch sprite, Texture2D spritesTex)
        {
        }
    }
}


text:
<?php

namespace app\models;

use Yii;

/**
 * This is the model class for table "embalaje".
 *
 * @property integer $idEmbalaje
 * @property string $nombre
 *
 * @property Producto[] $productos
 */
class Embalaje extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'embalaje';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['nombre'], 'required'],
            [['nombre'], 'string', 'max' => 45]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'idEmbalaje' => Yii::t('app', 'Id'),
            'nombre' => Yii::t('app', 'Nombre'),
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getProductos()
    {
        return $this->hasMany(Producto::className(), ['embalaje_idEmbalaje' => 'idEmbalaje']);
    }

    /**
     * @inheritdoc
     * @return EmbalajeQuery the active query used by this AR class.
     */
    public static function find()
    {
        return new EmbalajeQuery(get_called_class());
    }
}


text:
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Web;
using System.Text.RegularExpressions;

using LWAS.Extensible.Interfaces;

namespace LWAS.Infrastructure.Storage
{
	public class FileAgent : BaseAgent, IWatchdogSubscriber
	{
		protected static object SyncRoot = new object();
		protected Dictionary<string, Stream> Streams = new Dictionary<string, Stream>();
		protected string container;
		private IWatchdog _watchdog;
		public IWatchdog Watchdog
		{
			get
			{
				return this._watchdog;
			}
			set
			{
				this._watchdog = value;
				this._watchdog.WatchIt += new EventHandler(this._watchdog_WatchIt);
			}
		}
		public FileAgent()
		{
		}
		public FileAgent(string containerKey)
		{
			this.container = containerKey;
		}
		protected virtual string GetFileWithPath(string file)
		{
			string result;
			try
			{
				if (string.IsNullOrEmpty(this.container))
				{
                    if (!Path.IsPathRooted(file))
                        result = HttpContext.Current.Server.MapPath(file);
                    else
                        result = file;
				}
				else
				{
                    if (!Path.IsPathRooted(Path.Combine(this.container, file)))
                        result = HttpContext.Current.Server.MapPath(Path.Combine(this.container, file));
                    else
                        result = Path.Combine(this.container, file);
				}
			}
			catch (InvalidOperationException ex)
			{
				result = null;
			}
			return result;
		}
		public override Stream OpenStream(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException("key");
			}
			object syncRoot;
			Monitor.Enter(syncRoot = FileAgent.SyncRoot);
			Stream result;
			try
			{
				if (null != this.Streams && this.Streams.ContainsKey(key))
				{
					this.CloseStream(key);
				}
				string file = this.GetFileWithPath(key);
				Stream stream = File.Open(file, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
				if (null == stream)
				{
					throw new ApplicationException(string.Format("Couldn't open file '{0}'", file));
				}
				if (null == this.Streams)
				{
					this.Streams = new Dictionary<string, Stream>();
				}
				this.Streams.Add(key, stream);
				result = stream;
			}
			finally
			{
				Monitor.Exit(syncRoot);
			}
			return result;
		}
		public override void CloseStream(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException("key");
			}
			if (this.Streams.ContainsKey(key))
			{
				try
				{
					this.Streams[key].Close();
				}
				finally
				{
					this.Streams.Remove(key);
				}
			}
		}
		public override string Read(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException("key");
			}
			string file = this.GetFileWithPath(key);
			object syncRoot;
			Monitor.Enter(syncRoot = FileAgent.SyncRoot);
			string result;
			try
			{
				if (File.Exists(file))
				{
					result = File.ReadAllText(file);
				}
				else
				{
					result = string.Empty;
				}
			}
			finally
			{
				Monitor.Exit(syncRoot);
			}
			return result;
		}
		public override void Write(string key, string content)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException(key);
			}
			string file = this.GetFileWithPath(key);
			object syncRoot;
			Monitor.Enter(syncRoot = FileAgent.SyncRoot);
			try
			{
				if (!Directory.Exists(Path.GetDirectoryName(file)))
				{
					Directory.CreateDirectory(Path.GetDirectoryName(file));
				}
				File.WriteAllText(file, content);
			}
			finally
			{
				Monitor.Exit(syncRoot);
			}
		}
		public void Write(string key, Stream content)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException(key);
			}
			Stream fileStream = this.OpenStream(key);
			object syncRoot;
			Monitor.Enter(syncRoot = FileAgent.SyncRoot);
            try
            {
                FileAgent.CopyStream(content, fileStream);
            }
            catch (Exception ex)
            {
            }
			finally
			{
				Monitor.Exit(syncRoot);
			}
			this.CloseStream(key);
		}
		public static void CopyStream(Stream input, Stream output)
		{
			byte[] buffer = new byte[8192];
			int len;
			while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
			{
				output.Write(buffer, 0, len);
			}
		}
		public override void Erase(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException("key");
			}
			string file = this.GetFileWithPath(key);
			object syncRoot;
			Monitor.Enter(syncRoot = FileAgent.SyncRoot);
			try
			{
				if (File.Exists(file))
				{
					File.Delete(file);
				}
			}
			finally
			{
				Monitor.Exit(syncRoot);
			}
		}
		public override IList<string> List()
		{
            if (null == this.Streams)
                return new List<string>();
			string[] keys = new string[this.Streams.Count];
			this.Streams.Keys.CopyTo(keys, 0);
			return keys;
		}

        public override IEnumerable<string> ListAll(string filter)
        {
            if (String.IsNullOrEmpty(container))
                yield break;
            string path = container;
            if (!Path.IsPathRooted(path))
                path = HttpContext.Current.Server.MapPath(path);
            foreach (string f in Directory.GetFiles(path, filter))
                yield return Path.GetFileName(f);
        }

		public override bool HasKey(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				throw new ArgumentNullException("key");
			}
			return File.Exists(this.GetFileWithPath(key));
		}
		public override void ReplaceKey(string oldkey, string newkey)
		{
			if (string.IsNullOrEmpty(oldkey))
			{
				throw new ArgumentNullException("oldkey");
			}
			if (string.IsNullOrEmpty(newkey))
			{
				throw new ArgumentNullException("newkey");
			}
			if (this.HasKey(oldkey))
			{
				object syncRoot;
				Monitor.Enter(syncRoot = FileAgent.SyncRoot);
				try
				{
					Directory.Move(this.GetFileWithPath(oldkey), this.GetFileWithPath(newkey));
				}
				finally
				{
					Monitor.Exit(syncRoot);
				}
			}
		}
		private void _watchdog_WatchIt(object sender, EventArgs e)
		{
			this.CleanUp();
		}
		public override void CleanUp()
		{
            if (null == this.Streams) return;

			foreach (string key in this.List())
			{
				if (this.Streams.ContainsKey(key))
				{
					try
					{
						this.Streams[key].Close();
					}
					finally
					{
						this.Streams.Remove(key);
					}
				}
			}
			this.Streams = null;
		}

        public override string Sanitize(string key)
        {
            string temp = Regex.Escape(new string(Path.GetInvalidFileNameChars()));
            string invalid = string.Format(@"[{0}]+", temp);
            return Regex.Replace(key, invalid, "_");
        }
	}
}


text:
<?xml version="1.0" encoding="UTF-8"?>

		<item value="289" key="DIALOG_WIDTH"/>
		<item value="356" key="DIALOG_HEIGHT"/>
		<item value="1|Lucida Grande|11.0|0|COCOA|1|LucidaGrande" key="DIALOG_FONT_NAME"/>

		<item value="800" key="DIALOG_WIDTH"/>
		<item value="640" key="DIALOG_HEIGHT"/>
		<item value="1|Lucida Grande|11.0|0|COCOA|1|LucidaGrande" key="DIALOG_FONT_NAME"/>


text:
/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Should you need to contact me, the author, you can do so either by
 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb/input.h>
#include <linux/hid.h>

/*
 * Version Information
 */
#define DRIVER_VERSION "v1.6"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
#define DRIVER_LICENSE "GPL"

MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);

struct usb_mouse {
	char name[128];
	char phys[64];
	struct usb_device *usbdev;
	struct input_dev *dev;
	struct urb *irq;

	signed char *data;
	dma_addr_t data_dma;
};

static void usb_mouse_irq(struct urb *urb)
{
	struct usb_mouse *mouse = urb->context;
	signed char *data = mouse->data;
	struct input_dev *dev = mouse->dev;
	int status;

	switch (urb->status) {
	case 0:			/* success */
		break;
	case -ECONNRESET:	/* unlink */
	case -ENOENT:
	case -ESHUTDOWN:
		return;
	/* -EPIPE:  should clear the halt */
	default:		/* error */
		goto resubmit;
	}

	input_report_key(dev, BTN_LEFT,   data[0] & 0x01);
	input_report_key(dev, BTN_RIGHT,  data[0] & 0x02);
	input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
	input_report_key(dev, BTN_SIDE,   data[0] & 0x08);
	input_report_key(dev, BTN_EXTRA,  data[0] & 0x10);

	input_report_rel(dev, REL_X,     data[1]);
	input_report_rel(dev, REL_Y,     data[2]);
	input_report_rel(dev, REL_WHEEL, data[3]);

	input_sync(dev);
resubmit:
	status = usb_submit_urb (urb, GFP_ATOMIC);
	if (status)
		err ("can't resubmit intr, %s-%s/input0, status %d",
				mouse->usbdev->bus->bus_name,
				mouse->usbdev->devpath, status);
}

static int usb_mouse_open(struct input_dev *dev)
{
	struct usb_mouse *mouse = dev->private;

	mouse->irq->dev = mouse->usbdev;
	if (usb_submit_urb(mouse->irq, GFP_KERNEL))
		return -EIO;

	return 0;
}

static void usb_mouse_close(struct input_dev *dev)
{
	struct usb_mouse *mouse = dev->private;

	usb_kill_urb(mouse->irq);
}

static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usb_host_interface *interface;
	struct usb_endpoint_descriptor *endpoint;
	struct usb_mouse *mouse;
	struct input_dev *input_dev;
	int pipe, maxp;

	interface = intf->cur_altsetting;

	if (interface->desc.bNumEndpoints != 1)
		return -ENODEV;

	endpoint = &interface->endpoint[0].desc;
	if (!usb_endpoint_is_int_in(endpoint))
		return -ENODEV;

	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));

	mouse = kzalloc(sizeof(struct usb_mouse), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!mouse || !input_dev)
		goto fail1;

	mouse->data = usb_buffer_alloc(dev, 8, GFP_ATOMIC, &mouse->data_dma);
	if (!mouse->data)
		goto fail1;

	mouse->irq = usb_alloc_urb(0, GFP_KERNEL);
	if (!mouse->irq)
		goto fail2;

	mouse->usbdev = dev;
	mouse->dev = input_dev;

	if (dev->manufacturer)
		strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));

	if (dev->product) {
		if (dev->manufacturer)
			strlcat(mouse->name, " ", sizeof(mouse->name));
		strlcat(mouse->name, dev->product, sizeof(mouse->name));
	}

	if (!strlen(mouse->name))
		snprintf(mouse->name, sizeof(mouse->name),
			 "USB HIDBP Mouse %04x:%04x",
			 le16_to_cpu(dev->descriptor.idVendor),
			 le16_to_cpu(dev->descriptor.idProduct));

	usb_make_path(dev, mouse->phys, sizeof(mouse->phys));
	strlcat(mouse->phys, "/input0", sizeof(mouse->phys));

	input_dev->name = mouse->name;
	input_dev->phys = mouse->phys;
	usb_to_input_id(dev, &input_dev->id);
	input_dev->cdev.dev = &intf->dev;

	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
	input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
	input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
	input_dev->relbit[0] |= BIT(REL_WHEEL);

	input_dev->private = mouse;
	input_dev->open = usb_mouse_open;
	input_dev->close = usb_mouse_close;

	usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
			 (maxp > 8 ? 8 : maxp),
			 usb_mouse_irq, mouse, endpoint->bInterval);
	mouse->irq->transfer_dma = mouse->data_dma;
	mouse->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	input_register_device(mouse->dev);

	usb_set_intfdata(intf, mouse);
	return 0;

fail2:	usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
fail1:	input_free_device(input_dev);
	kfree(mouse);
	return -ENOMEM;
}

static void usb_mouse_disconnect(struct usb_interface *intf)
{
	struct usb_mouse *mouse = usb_get_intfdata (intf);

	usb_set_intfdata(intf, NULL);
	if (mouse) {
		usb_kill_urb(mouse->irq);
		input_unregister_device(mouse->dev);
		usb_free_urb(mouse->irq);
		usb_buffer_free(interface_to_usbdev(intf), 8, mouse->data, mouse->data_dma);
		kfree(mouse);
	}
}

static struct usb_device_id usb_mouse_id_table [] = {
	{ USB_INTERFACE_INFO(USB_INTERFACE_CLASS_HID, USB_INTERFACE_SUBCLASS_BOOT,
		USB_INTERFACE_PROTOCOL_MOUSE) },
	{ }	/* Terminating entry */
};

MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);

static struct usb_driver usb_mouse_driver = {
	.name		= "usbmouse",
	.probe		= usb_mouse_probe,
	.disconnect	= usb_mouse_disconnect,
	.id_table	= usb_mouse_id_table,
};

static int __init usb_mouse_init(void)
{
	int retval = usb_register(&usb_mouse_driver);
	if (retval == 0)
		info(DRIVER_VERSION ":" DRIVER_DESC);
	return retval;
}

static void __exit usb_mouse_exit(void)
{
	usb_deregister(&usb_mouse_driver);
}

module_init(usb_mouse_init);
module_exit(usb_mouse_exit);


text:
// Use of this file is subject to the terms
// described in the LICENSE.TXT file that
// accompanies this file.
//
// Your use of this file indicates your
// acceptance of the terms described in
// LICENSE.TXT.
//
// http://www.freebt.net

#include "fbtusb.h"
#include "fbtpwr.h"
#include "fbtpnp.h"
#include "fbtdev.h"
#include "fbtrwr.h"
#include "fbtwmi.h"

#include "..\fbtusr.h"

// Handle power events
NTSTATUS FreeBT_DispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS           ntStatus;
    PIO_STACK_LOCATION irpStack;
    PUNICODE_STRING    tagString;
    PDEVICE_EXTENSION  deviceExtension;

    irpStack = IoGetCurrentIrpStackLocation(Irp);
    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

    // We don't queue power Irps, we'll only check if the
    // device was removed, otherwise we'll take appropriate
    // action and send it to the next lower driver. In general
    // drivers should not cause long delays while handling power
    // IRPs. If a driver cannot handle a power IRP in a brief time,
    // it should return STATUS_PENDING and queue all incoming
    // IRPs until the IRP completes.
    if (Removed == deviceExtension->DeviceState)
	{

        // Even if a driver fails the IRP, it must nevertheless call
        // PoStartNextPowerIrp to inform the Power Manager that it
        // is ready to handle another power IRP.
        PoStartNextPowerIrp(Irp);
        Irp->IoStatus.Status = ntStatus = STATUS_DELETE_PENDING;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return ntStatus;

    }

    if (NotStarted == deviceExtension->DeviceState)
	{
        // if the device is not started yet, pass it down
        PoStartNextPowerIrp(Irp);
        IoSkipCurrentIrpStackLocation(Irp);

        return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);

    }

    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::"));
    FreeBT_IoIncrement(deviceExtension);

    switch(irpStack->MinorFunction)
	{
    case IRP_MN_SET_POWER:
        // The Power Manager sends this IRP for one of the
        // following reasons:

        // 1) To notify drivers of a change to the system power state.
        // 2) To change the power state of a device for which
        //    the Power Manager is performing idle detection.

        // A driver sends IRP_MN_SET_POWER to change the power
        // state of its device if it's a power policy owner for the
        // device.
        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_SET_POWER\n"));
        IoMarkIrpPending(Irp);

        switch(irpStack->Parameters.Power.Type)
		{
        case SystemPowerState:
            HandleSystemSetPower(DeviceObject, Irp);
            ntStatus = STATUS_PENDING;
            break;

        case DevicePowerState:
            HandleDeviceSetPower(DeviceObject, Irp);
            ntStatus = STATUS_PENDING;
            break;

        }

        break;

    case IRP_MN_QUERY_POWER:
        // The Power Manager sends a power IRP with the minor
        // IRP code IRP_MN_QUERY_POWER to determine whether it
        // can safely change to the specified system power state
        // (S1-S5) and to allow drivers to prepare for such a change.
        // If a driver can put its device in the requested state,
        // it sets status to STATUS_SUCCESS and passes the IRP down.
        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_QUERY_POWER\n"));
        IoMarkIrpPending(Irp);

        switch(irpStack->Parameters.Power.Type)
		{
        case SystemPowerState:
            HandleSystemQueryPower(DeviceObject, Irp);
            ntStatus = STATUS_PENDING;
            break;

        case DevicePowerState:
            HandleDeviceQueryPower(DeviceObject, Irp);
            ntStatus = STATUS_PENDING;
            break;

        }

        break;

    case IRP_MN_WAIT_WAKE:
        // The minor power IRP code IRP_MN_WAIT_WAKE provides
        // for waking a device or waking the system. Drivers
        // of devices that can wake themselves or the system
        // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE
        // only to devices that always wake the system, such as
        // the power-on switch.
        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE\n"));
        IoMarkIrpPending(Irp);
        IoCopyCurrentIrpStackLocationToNext(Irp);
        IoSetCompletionRoutine(
                        Irp,
                        (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine,
                        deviceExtension,
                        TRUE,
                        TRUE,
                        TRUE);

        PoStartNextPowerIrp(Irp);
        ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
        if(!NT_SUCCESS(ntStatus))
		{
            FreeBT_DbgPrint(1, ("FBTUSB: Lower drivers failed the wait-wake Irp\n"));

        }

        ntStatus = STATUS_PENDING;

        // push back the count HERE and NOT in completion routine
        // a pending Wait Wake Irp should not impede stopping the device
        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE::"));
        FreeBT_IoDecrement(deviceExtension);
        break;

    case IRP_MN_POWER_SEQUENCE:
        // A driver sends this IRP as an optimization to determine
        // whether its device actually entered a specific power state.
        // This IRP is optional. Power Manager cannot send this IRP.
        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_POWER_SEQUENCE\n"));

    default:
        PoStartNextPowerIrp(Irp);
        IoSkipCurrentIrpStackLocation(Irp);
        ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
        if(!NT_SUCCESS(ntStatus))
		{
            FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchPower: Lower drivers failed this Irp\n"));

        }

        FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::"));
        FreeBT_IoDecrement(deviceExtension);

        break;

    }

    return ntStatus;

}

NTSTATUS HandleSystemQueryPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS           ntStatus;
    PDEVICE_EXTENSION  deviceExtension;
    SYSTEM_POWER_STATE systemState;
    PIO_STACK_LOCATION irpStack;

    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Entered\n"));

    // initialize variables
    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    systemState = irpStack->Parameters.Power.State.SystemState;

    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Query for system power state S%X\n"
                        "FBTUSB: HandleSystemQueryPower: Current system power state S%X\n",
                         systemState - 1,
                         deviceExtension->SysPower - 1));

    // Fail a query for a power state incompatible with waking up the system
    if ((deviceExtension->WaitWakeEnable) && (systemState > deviceExtension->DeviceCapabilities.SystemWake))
	{
        FreeBT_DbgPrint(1, ("FBTUSB: HandleSystemQueryPower: Query for an incompatible system power state\n"));

        PoStartNextPowerIrp(Irp);
        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower::"));
        FreeBT_IoDecrement(deviceExtension);

        return ntStatus;

    }

    // if querying for a lower S-state, issue a wait-wake
    if((systemState > deviceExtension->SysPower) && (deviceExtension->WaitWakeEnable))
	{
        IssueWaitWake(deviceExtension);

    }

    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(
            Irp,
            (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
            deviceExtension,
            TRUE,
            TRUE,
            TRUE);

    ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Leaving\n"));

    return STATUS_PENDING;

}

NTSTATUS HandleSystemSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
    NTSTATUS           ntStatus;
    PDEVICE_EXTENSION  deviceExtension;
    SYSTEM_POWER_STATE systemState;
    PIO_STACK_LOCATION irpStack;

    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Entered\n"));

    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    systemState = irpStack->Parameters.Power.State.SystemState;

    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Set request for system power state S%X\n"
                         "FBTUSB: HandleSystemSetPower: Current system power state S%X\n",
                         systemState - 1,
                         deviceExtension->SysPower - 1));

    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(
            Irp,
            (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
            deviceExtension,
            TRUE,
            TRUE,
            TRUE);

    ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
    FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Leaving\n"));

    return STATUS_PENDING;

}

NTSTATUS HandleDeviceQueryPower(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    NTSTATUS           ntStatus;
    PDEVICE_EXTENSION  deviceExtension;
    PIO_STACK_LOCATION irpStack;
    DEVICE_POWER_STATE deviceState;

    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Entered\n"));

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    deviceState = irpStack->Parameters.Power.State.DeviceState;

    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Query for device power state D%X\n"
                         "FBTUSB: HandleDeviceQueryPower: Current device power state D%X\n",
                         deviceState - 1,
                         deviceExtension->DevPower - 1));

    if (deviceExtension->WaitWakeEnable && deviceState > deviceExtension->DeviceCapabilities.DeviceWake)
	{
        PoStartNextPowerIrp(Irp);
        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::"));
        FreeBT_IoDecrement(deviceExtension);

        return ntStatus;

    }

    if (deviceState < deviceExtension->DevPower)
	{
        ntStatus = STATUS_SUCCESS;

    }

    else
	{
        ntStatus = HoldIoRequests(DeviceObject, Irp);
        if(STATUS_PENDING == ntStatus)
		{
            return ntStatus;

        }

    }

    // on error complete the Irp.
    // on success pass it to the lower layers
    PoStartNextPowerIrp(Irp);
    Irp->IoStatus.Status = ntStatus;
    Irp->IoStatus.Information = 0;
    if(!NT_SUCCESS(ntStatus))
	{
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

    }

    else
	{
        IoSkipCurrentIrpStackLocation(Irp);
        ntStatus=PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);

    }

    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::"));
    FreeBT_IoDecrement(deviceExtension);

    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Leaving\n"));

    return ntStatus;

}

NTSTATUS SysPoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
{
    NTSTATUS           ntStatus;
 	PIO_STACK_LOCATION irpStack;

    ntStatus = Irp->IoStatus.Status;
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Entered\n"));

    // lower drivers failed this Irp
    if(!NT_SUCCESS(ntStatus))
	{
        PoStartNextPowerIrp(Irp);
        FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine::"));
        FreeBT_IoDecrement(DeviceExtension);

        return STATUS_SUCCESS;

    }

    // ..otherwise update the cached system power state (IRP_MN_SET_POWER)
    if(irpStack->MinorFunction == IRP_MN_SET_POWER)
	{
        DeviceExtension->SysPower = irpStack->Parameters.Power.State.SystemState;

    }

    // queue device irp and return STATUS_MORE_PROCESSING_REQUIRED
    SendDeviceIrp(DeviceObject, Irp);

    FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Leaving\n"));

    return STATUS_MORE_PROCESSING_REQUIRED;

}

VOID SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP SIrp )
{
    NTSTATUS                  ntStatus;
    POWER_STATE               powState;
    PDEVICE_EXTENSION         deviceExtension;
    PIO_STACK_LOCATION        irpStack;
    SYSTEM_POWER_STATE        systemState;
    DEVICE_POWER_STATE        devState;
    PPOWER_COMPLETION_CONTEXT powerContext;

    irpStack = IoGetCurrentIrpStackLocation(SIrp);
    systemState = irpStack->Parameters.Power.State.SystemState;
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

    FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Entered\n"));

    // Read out the D-IRP out of the S->D mapping array captured in QueryCap's.
    // we can choose deeper sleep states than our mapping but never choose
    // lighter ones.
    devState = deviceExtension->DeviceCapabilities.DeviceState[systemState];
    powState.DeviceState = devState;

    powerContext = (PPOWER_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT));
    if (!powerContext)
	{
        FreeBT_DbgPrint(1, ("FBTUSB: SendDeviceIrp: Failed to alloc memory for powerContext\n"));
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;

    }

    else
	{
        powerContext->DeviceObject = DeviceObject;
        powerContext->SIrp = SIrp;

        // in win2k PoRequestPowerIrp can take fdo or pdo.
        ntStatus = PoRequestPowerIrp(
                            deviceExtension->PhysicalDeviceObject,
                            irpStack->MinorFunction,
                            powState,
                            (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine,
                            powerContext,
                            NULL);

    }

    if (!NT_SUCCESS(ntStatus))
	{
        if (powerContext)
		{
            ExFreePool(powerContext);

        }

        PoStartNextPowerIrp(SIrp);
        SIrp->IoStatus.Status = ntStatus;
        SIrp->IoStatus.Information = 0;
        IoCompleteRequest(SIrp, IO_NO_INCREMENT);

        FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp::"));
        FreeBT_IoDecrement(deviceExtension);

    }

    FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Leaving\n"));

}

VOID DevPoCompletionRoutine(
    IN PDEVICE_OBJECT DeviceObject,
    IN UCHAR MinorFunction,
    IN POWER_STATE PowerState,
    IN PVOID Context,
    IN PIO_STATUS_BLOCK IoStatus
    )
{
    PIRP                      sIrp;
    PDEVICE_EXTENSION         deviceExtension;
    PPOWER_COMPLETION_CONTEXT powerContext;

    powerContext = (PPOWER_COMPLETION_CONTEXT) Context;
    sIrp = powerContext->SIrp;
    deviceExtension = (PDEVICE_EXTENSION) powerContext->DeviceObject->DeviceExtension;

    FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Entered\n"));

    sIrp->IoStatus.Status = IoStatus->Status;
    PoStartNextPowerIrp(sIrp);
    sIrp->IoStatus.Information = 0;
    IoCompleteRequest(sIrp, IO_NO_INCREMENT);

    FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine::"));
    FreeBT_IoDecrement(deviceExtension);

    ExFreePool(powerContext);

    FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Leaving\n"));

}

NTSTATUS HandleDeviceSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    KIRQL              oldIrql;
    NTSTATUS           ntStatus;
    POWER_STATE        newState;
    PIO_STACK_LOCATION irpStack;
    PDEVICE_EXTENSION  deviceExtension;
    DEVICE_POWER_STATE newDevState,
                       oldDevState;

    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Entered\n"));

    deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    oldDevState = deviceExtension->DevPower;
    newState = irpStack->Parameters.Power.State;
    newDevState = newState.DeviceState;

    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Set request for device power state D%X\n"
                         "FBTUSB: HandleDeviceSetPower: Current device power state D%X\n",
                         newDevState - 1,
                         deviceExtension->DevPower - 1));

    if (newDevState < oldDevState)
	{

        FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Adding power to the device\n"));

        IoCopyCurrentIrpStackLocationToNext(Irp);
        IoSetCompletionRoutine(
                Irp,
                (PIO_COMPLETION_ROUTINE)FinishDevPoUpIrp,
                deviceExtension,
                TRUE,
                TRUE,
                TRUE);

        ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);

	}

    else
	{
        // newDevState >= oldDevState

        // hold I/O if transition from D0 -> DX (X = 1, 2, 3)
        // if transition from D1 or D2 to deeper sleep states,
        // I/O queue is already on hold.
        if(PowerDeviceD0 == oldDevState && newDevState > oldDevState)
		{
            // D0 -> DX transition
            FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Removing power from the device\n"));

            ntStatus = HoldIoRequests(DeviceObject, Irp);
            if (!NT_SUCCESS(ntStatus))
			{
                PoStartNextPowerIrp(Irp);
                Irp->IoStatus.Status = ntStatus;
                Irp->IoStatus.Information = 0;
                IoCompleteRequest(Irp, IO_NO_INCREMENT);

                FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower::"));
                FreeBT_IoDecrement(deviceExtension);

                return ntStatus;

            }

            else
			{
                goto HandleDeviceSetPower_Exit;

            }

        }

        else if (PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState)
		{
            // D0 -> D0
            // unblock the queue which may have been blocked processing
            // query irp
            FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: A SetD0 request\n"));

            KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
            deviceExtension->QueueState = AllowRequests;
            KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);

            ProcessQueuedRequests(deviceExtension);

        }

        IoCopyCurrentIrpStackLocationToNext(Irp);
        IoSetCompletionRoutine(
                Irp,
                (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
                deviceExtension,
                TRUE,
                TRUE,
                TRUE);

        ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
        if(!NT_SUCCESS(ntStatus))
		{
            FreeBT_DbgPrint(1, ("FBTUSB: HandleDeviceSetPower: Lower drivers failed a power Irp\n"));

        }

    }

HandleDeviceSetPower_Exit:

    FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Leaving\n"));

    return STATUS_PENDING;

}

NTSTATUS FinishDevPoUpIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
{
    NTSTATUS           ntStatus;

    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Entered\n"));

    ntStatus = Irp->IoStatus.Status;
    if(Irp->PendingReturned)
	{
        IoMarkIrpPending(Irp);

    }

    if(!NT_SUCCESS(ntStatus))
	{
        PoStartNextPowerIrp(Irp);

        FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp::"));
        FreeBT_IoDecrement(DeviceExtension);

        return STATUS_SUCCESS;

    }

    SetDeviceFunctional(DeviceObject, Irp, DeviceExtension);

    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Leaving\n"));

    return STATUS_MORE_PROCESSING_REQUIRED;

}

NTSTATUS SetDeviceFunctional(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
{
    KIRQL              oldIrql;
    NTSTATUS           ntStatus;
    POWER_STATE        newState;
    PIO_STACK_LOCATION irpStack;
    DEVICE_POWER_STATE newDevState, oldDevState;

    ntStatus = Irp->IoStatus.Status;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    newState = irpStack->Parameters.Power.State;
    newDevState = newState.DeviceState;
    oldDevState = DeviceExtension->DevPower;

    FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Entered\n"));

    // update the cached state
    DeviceExtension->DevPower = newDevState;

    // restore appropriate amount of state to our h/w
    // this driver does not implement partial context
    // save/restore.
    PoSetPowerState(DeviceObject, DevicePowerState, newState);
    if(PowerDeviceD0 == newDevState)
	{
        KeAcquireSpinLock(&DeviceExtension->DevStateLock, &oldIrql);
        DeviceExtension->QueueState = AllowRequests;
        KeReleaseSpinLock(&DeviceExtension->DevStateLock, oldIrql);

        ProcessQueuedRequests(DeviceExtension);

    }

    PoStartNextPowerIrp(Irp);
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional::"));
    FreeBT_IoDecrement(DeviceExtension);

    FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Leaving\n"));

    return STATUS_SUCCESS;

}

NTSTATUS FinishDevPoDnIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
{
    NTSTATUS           ntStatus;
    POWER_STATE        newState;
    PIO_STACK_LOCATION irpStack;

    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Entered\n"));

    ntStatus = Irp->IoStatus.Status;
    irpStack = IoGetCurrentIrpStackLocation(Irp);
    newState = irpStack->Parameters.Power.State;

    if (NT_SUCCESS(ntStatus) && irpStack->MinorFunction == IRP_MN_SET_POWER)
	{
        FreeBT_DbgPrint(3, ("FBTUSB: updating cache..\n"));
        DeviceExtension->DevPower = newState.DeviceState;
        PoSetPowerState(DeviceObject, DevicePowerState, newState);

    }

    PoStartNextPowerIrp(Irp);

    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp::"));
    FreeBT_IoDecrement(DeviceExtension);

    FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Leaving\n"));

    return STATUS_SUCCESS;

}

NTSTATUS HoldIoRequests(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)

{
    NTSTATUS               ntStatus;
    PIO_WORKITEM           item;
    PDEVICE_EXTENSION      deviceExtension;
    PWORKER_THREAD_CONTEXT context;

    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Entered\n"));

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    deviceExtension->QueueState = HoldRequests;

    context = (PWORKER_THREAD_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(WORKER_THREAD_CONTEXT));
    if(context)
	{
        item = IoAllocateWorkItem(DeviceObject);

        context->Irp = Irp;
        context->DeviceObject = DeviceObject;
        context->WorkItem = item;

        if (item)
		{
            IoMarkIrpPending(Irp);
            IoQueueWorkItem(item, HoldIoRequestsWorkerRoutine, DelayedWorkQueue, context);
            ntStatus = STATUS_PENDING;

        }

        else
		{
            FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Failed to allocate memory for workitem\n"));
            ExFreePool(context);
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;

        }

    }

    else
	{
        FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequests: Failed to alloc memory for worker thread context\n"));
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;

    }

    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Leaving\n"));

    return ntStatus;

}

VOID HoldIoRequestsWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
{
    PIRP                   irp;
    NTSTATUS               ntStatus;
    PDEVICE_EXTENSION      deviceExtension;
    PWORKER_THREAD_CONTEXT context;

    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Entered\n"));

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    context = (PWORKER_THREAD_CONTEXT) Context;
    irp = (PIRP) context->Irp;

    // wait for I/O in progress to finish.
    // the stop event is signalled when the counter drops to 1.
    // invoke FreeBT_IoDecrement twice: once each for the S-Irp and D-Irp.
    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
    FreeBT_IoDecrement(deviceExtension);

    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
    FreeBT_IoDecrement(deviceExtension);

    KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);

    // Increment twice to restore the count
    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
    FreeBT_IoIncrement(deviceExtension);

    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
    FreeBT_IoIncrement(deviceExtension);

    // now send the Irp down
    IoCopyCurrentIrpStackLocationToNext(irp);
    IoSetCompletionRoutine(
		irp,
		(PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
		deviceExtension,
		TRUE,
		TRUE,
		TRUE);

    ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
    if(!NT_SUCCESS(ntStatus))
	{
        FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequestsWorkerRoutine: Lower driver fail a power Irp\n"));

    }

    IoFreeWorkItem(context->WorkItem);
    ExFreePool((PVOID)context);

    FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Leaving\n"));

}

NTSTATUS QueueRequest(IN OUT PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
{
    KIRQL    oldIrql;
    NTSTATUS ntStatus;

    FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Entered\n"));

    ntStatus = STATUS_PENDING;

    ASSERT(HoldRequests == DeviceExtension->QueueState);

    KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);

    InsertTailList(&DeviceExtension->NewRequestsQueue, &Irp->Tail.Overlay.ListEntry);
    IoMarkIrpPending(Irp);
    IoSetCancelRoutine(Irp, CancelQueued);

    KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);

    FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Leaving\n"));

    return ntStatus;

}

VOID CancelQueued(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    PDEVICE_EXTENSION deviceExtension;
    KIRQL             oldIrql;

    FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Entered\n"));

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    oldIrql = Irp->CancelIrql;

    // Release the cancel spin lock
    IoReleaseCancelSpinLock(Irp->CancelIrql);

    // Acquire the queue lock
    KeAcquireSpinLockAtDpcLevel(&deviceExtension->QueueLock);

    // Remove the cancelled Irp from queue and release the lock
    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);

    KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);

    // complete with STATUS_CANCELLED
    Irp->IoStatus.Status = STATUS_CANCELLED;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Leaving\n"));

    return;

}

NTSTATUS IssueWaitWake(IN PDEVICE_EXTENSION DeviceExtension)
{
    POWER_STATE poState;
    NTSTATUS    ntStatus;

    FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Entered\n"));

    if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1))
	{
        return STATUS_DEVICE_BUSY;

    }

    InterlockedExchange(&DeviceExtension->FlagWWCancel, 0);

    // lowest state from which this Irp will wake the system
    poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake;
    ntStatus = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject,
                                 IRP_MN_WAIT_WAKE,
                                 poState,
                                 (PREQUEST_POWER_COMPLETE) WaitWakeCallback,
                                 DeviceExtension,
                                 &DeviceExtension->WaitWakeIrp);

    if(!NT_SUCCESS(ntStatus))
	{
        InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0);

    }

    FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Leaving\n"));

    return ntStatus;

}

VOID CancelWaitWake(IN PDEVICE_EXTENSION DeviceExtension)
{
    PIRP Irp;

    FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Entered\n"));

    Irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL);
    if(Irp)
	{
        IoCancelIrp(Irp);
        if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1))
		{
            PoStartNextPowerIrp(Irp);
            Irp->IoStatus.Status = STATUS_CANCELLED;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

        }

    }

    FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Leaving\n"));

}

NTSTATUS WaitWakeCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
{
    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Entered\n"));
    if(Irp->PendingReturned)
	{
        IoMarkIrpPending(Irp);

    }

    // Nullify the WaitWakeIrp pointer-the Irp is released
    // as part of the completion process. If it's already NULL,
    // avoid race with the CancelWaitWake routine.
    if(InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL))
	{
        PoStartNextPowerIrp(Irp);

        return STATUS_SUCCESS;

    }

    // CancelWaitWake has run.
    // If FlagWWCancel != 0, complete the Irp.
    // If FlagWWCancel == 0, CancelWaitWake completes it.
    if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1))
	{
        PoStartNextPowerIrp(Irp);

        return STATUS_CANCELLED;

    }

    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Leaving\n"));

    return STATUS_MORE_PROCESSING_REQUIRED;

}

VOID WaitWakeCallback(
    IN PDEVICE_OBJECT DeviceObject,
    IN UCHAR MinorFunction,
    IN POWER_STATE PowerState,
    IN PVOID Context,
    IN PIO_STATUS_BLOCK IoStatus)
{
    NTSTATUS               ntStatus;
    POWER_STATE            powerState;
    PDEVICE_EXTENSION      deviceExtension;

    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Entered\n"));

    deviceExtension = (PDEVICE_EXTENSION) Context;

    InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0);

    if(!NT_SUCCESS(IoStatus->Status))
	{
        return;

    }

    // wake up the device
    if(deviceExtension->DevPower == PowerDeviceD0)
	{
        FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Device already powered up...\n"));

        return;

    }

    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback::"));
    FreeBT_IoIncrement(deviceExtension);

    powerState.DeviceState = PowerDeviceD0;
    ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
                                 IRP_MN_SET_POWER,
                                 powerState,
                                 (PREQUEST_POWER_COMPLETE) WWIrpCompletionFunc,
                                 deviceExtension,
                                 NULL);

    if(deviceExtension->WaitWakeEnable)
	{
        IssueWaitWake(deviceExtension);

    }

    FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Leaving\n"));

    return;

}

PCHAR PowerMinorFunctionString (IN UCHAR MinorFunction)
{
    switch (MinorFunction)
	{
        case IRP_MN_SET_POWER:
            return "IRP_MN_SET_POWER\n";

        case IRP_MN_QUERY_POWER:
            return "IRP_MN_QUERY_POWER\n";

        case IRP_MN_POWER_SEQUENCE:
            return "IRP_MN_POWER_SEQUENCE\n";

        case IRP_MN_WAIT_WAKE:
            return "IRP_MN_WAIT_WAKE\n";

        default:
            return "IRP_MN_?????\n";

    }

}


text:
default['automount']['timeout'] = 600
default['automount']['autofs_package'] = 'autofs5'


text:
package uk.nhs.hdn.ihe.xds.builders;

import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.openhealthtools.ihe.bridge.type.PatientIdType;
import uk.nhs.hdn.number.NhsNumber;

import static uk.nhs.hdn.number.NhsNumber.valueOf;

public final class PatientIdBuilder
{
	@NotNull
	public static PatientIdType patientId(@NotNull @NonNls final String nhsNumber)
	{
		return patientId(valueOf(nhsNumber));
	}

	@NotNull
	public static PatientIdType patientId(@SuppressWarnings("TypeMayBeWeakened") @NotNull final NhsNumber nhsNumber)
	{
		return new PatientIdType(nhsNumber.normalised());
	}

	private PatientIdBuilder()
	{
	}
}


text:
package org.mrgeo.data.vector;

import org.mrgeo.geometry.Geometry;

import java.io.IOException;

public interface VectorWriter
{
void append(FeatureIdWritable key, Geometry value)
    throws IOException;

void close() throws IOException;
}


text:
#ifndef TESTDATASTREAM_H_
#define TESTDATASTREAM_H_

#include "unittest.h"

class CTestDataStream : public IUnitTest
{
    virtual HRESULT Run();
    UT_DECLARE_TEST_NAME("CTestDataStream");
};

#endif /* TESTDATASTREAM_H_ */


text:
Bedrock.Database = function () {
    let $ = Object.create (null);

    let Html = Bedrock.Html;

    // getAllFields - traverses an array of objects to produce an object that contains all
    // the field names, and all the associated values of each field
    $.getAllFields = function (database) {
        let allFields = {};
        for (let record of database) {
            let fields = Object.keys (record).sort ();
            for (let field of fields) {
                // make sure there is a field collector
                if (!(field in allFields)) {
                    allFields[field] = Object.create (null);
                }

                // put the value in, all the individual values if it's an array
                let values = record[field];
                if (values instanceof Array) {
                    for (let value of values) {
                        allFields[field][value] = value;
                    }
                } else {
                    allFields[field][values] = values;
                }
            }
        }

        // now replace each entry with a sorted array of its keys, and then save it
        let fields = Object.keys (allFields);
        for (let field of fields) {
            allFields[field] = Object.keys (allFields[field]).sort ();
        }
        return allFields;
    };

    //------------------------------------------------------------------------------------
    // Source is an interface declaration for something that returns a database
    $.Source = function () {
        let _ = Object.create (Bedrock.Base);

        _.init = function (database) {
            this.database = database;
            return this;
        };

        _.getDatabase = function () {
            return this.database;
        };

        return _;
    } ();

    //------------------------------------------------------------------------------------
    // database filter element is a single part of a deep tree query, they are grouped
    // together to build complex AND-based reduction operations
    $.FilterElement = function () {
        let _ = Object.create (Bedrock.Base);

        let doFilter = function (database, filterField, filterValue, shouldMatch = true) {
            let result = [];

            // if the search key is not specified, this is a pass-through filter, just return
            // what we started with
            if (filterField.length === 0) {
                return database;
            }

            // the individual filter function... we assume the user doesn't intend this to
            // be a regexp if it fails to compile
            let regExp;
            try {
                regExp = new RegExp (filterValue, 'i');
            } catch (error) {
                regExp = new RegExp (filterValue.replace (/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"), 'i')
            }
            let matchValue = function (value) {
                let matchResult = value.toString().match (regExp);
                return ((matchResult != null) === shouldMatch);
            };

            // otherwise, loop over all the records to see what passes
            for (let record of database) {
                // only pass records that contain the search key
                let match = (filterField in record);
                if (match === true) {
                    // get the value from the record, it might be a value, or an array of
                    // values, so we have to check and handle accordingly
                    let values = record[filterField];
                    if (values instanceof Array) {
                        let anyMatches = false;
                        for (let value of values) {
                            anyMatches = anyMatches || matchValue (value);
                        }
                        match = match && anyMatches;
                    } else {
                        match = match && matchValue (values);
                    }
                }

                // if we match, store the record into the result
                if (match === true) {
                    result.push (record);
                }
            }

            // return the result
            return result;
        };

        const FILTER_ELEMENT_FIELD = "filter-element-field";
        const FILTER_ELEMENT_VALUE = "filter-element-value";

        _.init = function (parameters) {
            // scope this so I can use it in closures
            let scope = this;

            let index = this.index = parameters.index;
            this.databaseSource = parameters.databaseSource;
            this.owner = parameters.owner;
            let filterField = parameters.initialValue.field;
            let filterValue = parameters.initialValue.value;
            let fieldKeys = parameters.fieldKeys;

            // create the element container
            this.elementContainer = Html.addElement (parameters.div, "div", { class: "bedrock-database-element-container", id: "filterElementContainer" + index });

            // create the select and editing elements inside the container
            this.countDiv = Html.addElement (this.elementContainer, "div", { class: "bedrock-database-element-text-div" });
            //this.fieldComboBox = addComboBoxElement (this.elementContainer, FILTER_ELEMENT_FIELD + index, fieldKeys, filterField, "FILTER FIELD");

            let fieldComboBox = this.fieldComboBox = Bedrock.ComboBox.new ({
                style: { width: "100%" },
                parentElementId: this.elementContainer.id,
                placeholder: "(FILTER FIELD)",
                inputElementId: FILTER_ELEMENT_FIELD + index,
                options: fieldKeys,
                value: filterField,
                onchange: function () {
                    scope.valueComboBox.value = "";
                    scope.update ();
                }
            });

            let database = this.databaseSource.getDatabase ();
            let allFields = $.getAllFields (database);
            //this.valueElement = addComboBoxElement(this.elementContainer, FILTER_ELEMENT_VALUE + index, (filterField in allFields) ? allFields[filterField] : [], filterValue, "FILTER VALUE");

            let valueComboBox = this.valueComboBox = Bedrock.ComboBox.new ({
                style: { width: "100%" },
                parentElementId: this.elementContainer.id,
                placeholder: "(FILTER VALUE)",
                inputElementId: FILTER_ELEMENT_VALUE + index,
                options: (filterField in allFields) ? allFields[filterField] : [],
                value: filterValue,
                onchange: function () {
                    scope.finishUpdate ();
                }
            });

            this.filteredDatabase = doFilter (database, filterField, filterValue, true);
            this.countDiv.innerHTML = this.filteredDatabase.length + "/" + database.length;

            return this;
        };

        _.update = function () {
            // rebuild the value options
            let database = this.databaseSource.getDatabase ();
            let allFields = $.getAllFields (database);
            this.valueComboBox.setOptions ((this.fieldComboBox.value in allFields) ? allFields[this.fieldComboBox.value] : []);

            this.finishUpdate ();
        };

        _.finishUpdate = function () {
            let database = this.databaseSource.getDatabase ();
            this.filteredDatabase = doFilter (database, this.fieldComboBox.value, this.valueComboBox.value, true);
            this.countDiv.innerHTML = this.filteredDatabase.length + "/" + database.length;
            this.owner.push (this.index);
        };

        _.onValueChange = function (updatedControl) {
            this.update ();
        };

        _.getDatabase = function () {
            return this.filteredDatabase;
        };

        _.setFieldValue = function (filterField, filterValue) {
            // set the filter field value
            this.fieldComboBox.value = filterField;

            // rebuild the value select
            let database = this.databaseSource.getDatabase ();
            let allFields = $.getAllFields (database);
            this.valueComboBox
                .setOptions ((this.fieldComboBox.value in allFields) ? allFields[this.fieldComboBox.value] : [])
                .value = filterValue;
        };

        return _;
    } ();

    //------------------------------------------------------------------------------------
    $.SortElement = function () {
        let _ = Object.create (Bedrock.Base);

        let makeControls = function (index, field, type, asc, fieldKeys) {
            let innerHTML =
                div ("bedrock-element-div", makeSelectHTML ("sortElementSelectKey" + index, fieldKeys, field, "SORT FIELD")) +
                div ("bedrock-element-div", makeSelectHTML ("sortElementSelectType" + index, ["AUTO", "NUMERIC", "ALPHABETIC", "DATE"], type, "SORT TYPE")) +
                div ("bedrock-element-div", makeSelectHTML ("sortElementSelectAsc" + index, ["ASCENDING", "DESCENDING"], asc, "SORT ASC"));
            return innerHTML;
        };

        _.init = function (parameters) {
            this.index = parameters.index;
            this.owner = parameters.owner;
            this.sortField = parameters.sortField;
            this.sortType = parameters.sortType;
            this.sortAsc = parameters.sortAsc;

            // create the select and editing elements inside the supplied div id
            document.getElementById ("sortElementContainer" + parameters.index).innerHTML = makeControls (parameters.index, this.sortField, this.sortType, this.sortAsc, parameters.fieldKeys);

            return this;
        };

        return _;
    } ();

    //------------------------------------------------------------------------------------
    $.Filter = function () {
        let _ = Object.create (Bedrock.Base);

        let conditionValues = function (values = [], elementCount = 0) {
            for (let i = values.length; i < elementCount; ++i) {
                values.push ({});
            }
            for (let value of values) {
                value.field = ("field" in value) ? value.field : "";
                value.value = ("value" in value) ? value.value : "";
            }
            return values;
        };

        _.init = function (parameters) {
            this.databaseSource = parameters.databaseSource;
            this.elementCount = parameters.elementCount;
            this.owner = parameters.owner;
            this.fieldKeys = parameters.fieldKeys;
            this.initialValues = conditionValues (parameters.initialValues, parameters.elementCount);
            return this.reset ();
        };

        _.finish = function () {
            // hide unused filter elements and call out to the parent
            let filters = this.filters;
            let length = filters.length;
            let index = length - 1;

            // this was the last one, reverse up the list looking for the last full filter
            while ((filters[index].fieldComboBox.value.length == 0) && (index > 0)) {
                --index;
            }
            if (filters[index].fieldComboBox.value.length > 0) {
                ++index;
            }
            if (index < length) {
                filters[index].elementContainer.style.display = "inline-block";
                while (++index < length) {
                    filters[index].elementContainer.style.display = "none";
                }
            }

            // and finally call the outbound push
            this.owner.push (this.getDatabase ());
        };

        _.push = function (index) {
            let filters = this.filters;
            let length = filters.length;
            if ((index + 1) < length) {
                filters[index + 1].update ();
            } else {
                // notify the receiver we've finished updating
                this.finish ();
            }
            return this;
        };

        _.update = function () {
            return this.push (-1);
        };

        _.onValueChange = function (updatedControl) {
            let index = updatedControl.id.match (/\d+$/)[0];
            this.filters[index].onValueChange (updatedControl);
        };

        _.getDatabase = function () {
            return this.filters[this.filters.length - 1].getDatabase ();
        };

        _.setValues = function (values) {
            let elementCount = this.elementCount;
            let filters = this.filters;
            values = conditionValues (values, elementCount);
            for (let i = 0; i < elementCount; ++i) {
                filters[i].setFieldValue (values[i].field, values[i].value);
            }
            return this.update ();
        };

        _.reset = function () {
            // scope this so I can use it in closures
            let scope = this;

            // get the filter container and clean it out
            let filterContainer = document.getElementById ("filterContainer");
            while (filterContainer.firstChild) {
                filterContainer.removeChild (filterContainer.firstChild);
            }

            // now create the filter elements
            this.filters = [];
            for (let index = 0; index < this.elementCount; ++index) {
                this.filters.push ($.FilterElement.new ({
                    div: filterContainer,
                    index: index,
                    fieldKeys: this.fieldKeys,
                    initialValue: this.initialValues[index],
                    databaseSource: (index > 0) ? this.filters[index - 1] : this.databaseSource,
                    owner: this
                }));
            }

            // drop in the clear button
            let clearButtonElementContainer = Html.addElement (filterContainer, "div", { class: "bedrock-database-element-container" });
            Html.addElement (clearButtonElementContainer, "div", { class: "bedrock-database-element-text-div" });
            Html.addElement (clearButtonElementContainer, "button", {
                class: "bedrock-database-clear-button", onclick: function () {
                    scope.reset ();
                }
            }).innerHTML = "CLEAR";

            // and notify the receiver that we've finished setting up
            this.finish ();

            return this;
        };

        return _;
    } ();

    //------------------------------------------------------------------------------------
    $.Sort = function () {
        let _ = Object.create (Bedrock.Base);

        _.init = function (parameters) {
            this.elementCount = parameters.elementCount;
            this.owner = parameters.owner;
            this.fieldKeys = parameters.fieldKeys;

            // create the select and editing elements
            let sortContainerHTML = "";
            for (let index = 0; index < this.elementCount; ++index) {
                sortContainerHTML += block ("div", { class: "bedrock-database-element-container", id: "sortElementContainer" + index }, "");
            }

            // drop in the clear button
            sortContainerHTML +=
                div ("bedrock-database-element-container",
                    div ("bedrock-database-element-text-div", "") +
                    div ("bedrock-element-div",
                        block ("button", { class: "bedrockClearButton", type: "button", onclick: "theBedrock.sort.reset ();" }, "CLEAR")
                    )
                );

            document.getElementById ("sortContainer").innerHTML = sortContainerHTML;

            this.sorts = [];
            for (let index = 0; index < this.elementCount; ++index) {
                this.sorts.push ($.SortElement.new ({
                    index: index,
                    fieldKeys: this.fieldKeys,
                    owner: this,
                    sortField: "",
                    sortType: "",
                    sortAsc: ""
                }));
            }

            return this;
        };

        return _;
    } ();

    $.Container = function () {
        let _ = Object.create (Bedrock.Base);

        _.init = function (parameters) {
            this.databaseSource = $.Source.new (parameters.database);
            this.fieldKeys = Object.keys ($.getAllFields (parameters.database)).sort ();
            this.onUpdate = parameters.onUpdate;

            // get the top level container
            let bedrockContainerId = ("div" in parameters) ? parameters.div : "bedrock-database-container";
            let bedrockContainer = document.getElementById (bedrockContainerId);
            Html.addElement (bedrockContainer, "div", { class: "bedrock-database-group-container", id: "filterContainer" });
            Html.addElement (bedrockContainer, "div", { class: "bedrock-database-group-container", id: "sortContainer" });

            // create the filter
            this.filter = $.Filter.new ({
                databaseSource: this.databaseSource,
                fieldKeys: this.fieldKeys,
                owner: this,
                elementCount: (parameters.filterElementCount !== undefined) ? parameters.filterElementCount : 4,
                initialValues: parameters.filterValues
            });
/*
            // create the sort control
            this.sort = $.Sort.new ({
                databaseSource: this.databaseSource,
                fieldKeys: this.fieldKeys,
                owner: this,
                elementCount: (typeof parameters.sortElementCount !== "undefined") ? parameters.sortElementCount : 2,
                initialValues: parameters.sortValues,
            });
            */

            return this;
        };

        _.push = function (db) {
            // do the sort

            // pass the result on to the update handler
            this.onUpdate (db);
        };

        return _;
    } ();

    return $;
} ();


text:
function texturize(target, texture)
  if type(texture)=='string' then
    texture=love.image.newImageData(texture)
  end
  tx, ty=texture:getWidth(), texture:getHeight()
  local function placeTexture(x, y, r, g, b, a)
    if r+g+b==0 then -- black
      return 0,0,0,0
    else -- non-black, needs a texture
      return texture:getPixel(x%tx, y%ty)
    end
  end
  local id=target:getImageData()
  id:mapPixel(placeTexture)
  return love.graphics.newImage(id)
end

-- make texturized polygon
function makePolygon(V, texture)
  local t=love.image.newImageData(texture)

  local minX, maxX, minY, maxY
  for n=1,#V, 2 do
    if not minX or minX>V[n] then minX=V[n] end
    if not maxX or maxX<V[n] then maxX=V[n] end
    if not minY or minY>V[n+1] then minY=V[n+1] end
    if not maxY or maxY<V[n+1] then maxY=V[n+1] end
  end
  local w,h=maxX-minX+1, maxY-minY+1
  local fb
  if love.graphics.newCanvas then -- 0.8+
    fb=love.graphics.newCanvas(w, h)
  else --0.7
    fb=love.graphics.newFramebuffer(w, h)
  end
  love.graphics.setCanvas(fb)
  love.graphics.setColor(255,255,255)
  love.graphics.translate(-minX, -minY)
  love.graphics.polygon('fill', V)
  love.graphics.translate(minX, minY)
  love.graphics.setCanvas()
  return texturize(fb, texture)
end

function love.load()
  local vertices={0,0, 100,0, 200,100, 100,400, 0,300, -100,200, 0,0}
  local textures={'face-crying.png', 'face-grin.png', 'face-plain.png', 'face-sad.png', 'face-smile-big.png', 'face-smile.png', 'face-surprise.png', 'face-wink.png'}
  Polygons={}
  for k,v in ipairs(textures) do
    Polygons[k]=makePolygon(vertices, v)
  end
  X, Y, r=200,200,0
end

function love.draw()
  local idx=math.floor(5*r%#Polygons)+1
  love.graphics.draw(Polygons[1], X-5, Y-5, 0, 1, 1, X, Y)
  love.graphics.draw(Polygons[idx], X, Y, r, 1, 1, X, Y)
end

function love.update(dt)
  r=r+dt
end