text:
[![API Documentation][godoc-svg]][godoc-url] [![MIT License][license-svg]][license-url]

This package implements support for executing PHP scripts, exporting Go variables for use in PHP contexts, attaching Go method receivers as PHP classes and returning PHP variables for use in Go contexts.

Both PHP 5.x and PHP 7.x series are supported.

## Building

Building this package requires that you have PHP installed as a library. For most Linux systems, this can usually be found in the `php-embed` package, or variations thereof.

Once the PHP library is available, the bindings can be compiled with `go build` and are `go get`-able.

**Note**: Building against PHP 5.x requires that the `php5` tag is provided, i.e.:

```bash
go get -tags php5 github.com/deuill/go-php
```

This is due to the fact that PHP 7.x is the default build target.

## Status

Executing PHP [script files][Context.Exec] as well as [inline strings][Context.Eval] is supported and stable.

[Binding Go values][NewValue] as PHP variables is allowed for most base types, and PHP values returned from eval'd strings can be converted and used in Go contexts as `interface{}` values.

It is possible to [attach Go method receivers][NewReceiver] as PHP classes, with full support for calling expored methods, as well as getting and setting embedded fields (for `struct`-type method receivers).

### Caveats

Be aware that, by default, PHP is **not** designed to be used in multithreaded environments (which severely restricts the use of these bindings with Goroutines) if not built with [ZTS support](https://secure.php.net/manual/en/pthreads.requirements.php). However, ZTS support has seen major refactoring between PHP 5 and PHP 7, and as such is currently unsupported by this package.

Currently, it is recommended to either sync use of seperate Contexts between Goroutines, or share a single Context among all running Goroutines.

## Roadmap

Currently, the package lacks in several respects:

  * ZTS/multi-threading support. This basically means using Go-PHP in Goroutines is severely limited.
  * Documentation and examples, both package-level and external.
  * Performance. There's no reason to believe Go-PHP suffers from any serious performance issues in particular, but adding benchmarks, especially compared against vanilla PHP, might help.
  * Your feature request here?

These items will be tackled in order of significance (which may not be the order shown above).

## Usage

### Basic

Executing a script is simple:

```go
package main

import (
    php "github.com/deuill/go-php"
    "os"
)

func main() {
    engine, _ := php.New()

    context, _ := engine.NewContext()
    context.Output = os.Stdout

    context.Exec("index.php")
    engine.Destroy()
}
```

The above will execute script file `index.php` located in the current folder and will write any output to the `io.Writer` assigned to `Context.Output` (in this case, the standard output).

### Binding and returning variables

The following example demonstrates binding a Go variable to the running PHP context, and returning a PHP variable for use in Go:

```go
package main

import (
    "fmt"
    php "github.com/deuill/go-php"
)

func main() {
    engine, _ := php.New()
    context, _ := engine.NewContext()

    var str string = "Hello"
    context.Bind("var", str)

    val, _ := context.Eval("return $var.' World';")
    fmt.Printf("%s", val.Interface())
    // Prints 'Hello World' back to the user.

    engine.Destroy()
}
```

A string value "Hello" is attached using `Context.Bind` under a name `var` (available in PHP as `$var`). A script is executed inline using `Context.Eval`, combinding the attached value with a PHP string and returning it to the user.

Finally, the value is returned as an `interface{}` using `Value.Interface()` (one could also use `Value.String()`, though the both are equivalent in this case).

## License

All code in this repository is covered by the terms of the MIT License, the full text of which can be found in the LICENSE file.

[godoc-url]: https://godoc.org/github.com/deuill/go-php
[godoc-svg]: https://godoc.org/github.com/deuill/go-php?status.svg

[license-url]: https://github.com/deuill/go-php/blob/master/LICENSE
[license-svg]: https://img.shields.io/badge/license-MIT-blue.svg

[Context.Exec]: https://godoc.org/github.com/deuill/go-php/engine#Context.Exec
[Context.Eval]: https://godoc.org/github.com/deuill/go-php/engine#Context.Eval
[NewValue]:     https://godoc.org/github.com/deuill/go-php/engine#NewValue
[NewReceiver]:  https://godoc.org/github.com/deuill/go-php/engine#NewReceiver


text:
package xyz.vopen.cartier.commons.yaml.emitter;

import static xyz.vopen.cartier.commons.yaml.parser.EventType.*;

import xyz.vopen.cartier.commons.yaml.parser.CollectionStartEvent;
import xyz.vopen.cartier.commons.yaml.parser.DocumentEndEvent;
import xyz.vopen.cartier.commons.yaml.parser.DocumentStartEvent;
import xyz.vopen.cartier.commons.yaml.parser.Event;
import xyz.vopen.cartier.commons.yaml.parser.MappingStartEvent;
import xyz.vopen.cartier.commons.yaml.parser.NodeEvent;
import xyz.vopen.cartier.commons.yaml.parser.Parser;
import xyz.vopen.cartier.commons.yaml.parser.ScalarEvent;
import xyz.vopen.cartier.commons.yaml.parser.SequenceStartEvent;

import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Pattern;

/** Converts events into YAML output.
 * @author Nathan Sweet
 * @author Ola Bini */
public class Emitter {
	static private final Pattern HANDLE_FORMAT = Pattern.compile("^![-\\w]*!$");
	static private final Pattern ANCHOR_FORMAT = Pattern.compile("^[-\\w]*$");

	final EmitterConfig config;
	final EmitterWriter writer;
	final EmitterState[] table = new EmitterState[18];
	int state = S_STREAM_START;
	final List<Integer> states = new ArrayList();
	final List<Event> events = new ArrayList();
	final List<Integer> indents = new ArrayList();
	boolean isVersion10 = false;
	Event event;
	int flowLevel = 0;
	int indent = -1;
	boolean mappingContext = false;
	boolean simpleKeyContext = false;
	Map<String, String> tagPrefixes;
	String preparedTag, preparedAnchor;
	ScalarAnalysis analysis;
	char style = 0;

	public Emitter (Writer writer) {
		this(writer, new EmitterConfig());
	}

	public Emitter (Writer writer, EmitterConfig config) {
		this.config = config;
		if (writer == null) throw new IllegalArgumentException("stream cannot be null.");
		if (!(writer instanceof BufferedWriter)) writer = new BufferedWriter(writer);
		this.writer = new EmitterWriter(writer);
		initStateTable();
	}

	public void emit (Event event) throws IOException, EmitterException {
		if (event == null) throw new IllegalArgumentException("event cannot be null.");
		events.add(event);
		while (!needMoreEvents()) {
			this.event = events.remove(0);
			table[state].expect();
			this.event = null;
		}
	}

	public void close () throws IOException {
		writer.close();
	}

	private boolean needMoreEvents () {
		if (events.isEmpty()) return true;
		event = events.get(0);
		if (event == null) return false;
		switch (event.type) {
		case DOCUMENT_START:
			return needEvents(1);
		case SEQUENCE_START:
			return needEvents(2);
		case MAPPING_START:
			return needEvents(3);
		default:
			return false;
		}
	}

	private boolean needEvents (int count) {
		int level = 0;
		Iterator<Event> iter = events.iterator();
		iter.next();
		while (iter.hasNext()) {
			Event curr = iter.next();
			if (curr.type == DOCUMENT_START || curr.type == MAPPING_START || curr.type == SEQUENCE_START)
				level++;
			else if (curr.type == DOCUMENT_END || curr.type == MAPPING_END || curr.type == SEQUENCE_END)
				level--;
			else if (curr.type == STREAM_END) level = -1;
			if (level < 0) return false;
		}
		return events.size() < count + 1;
	}

	private void initStateTable () {
		table[S_STREAM_START] = new EmitterState() {
			public void expect () {
				if (event.type == STREAM_START) {
					writer.writeStreamStart();
					state = S_FIRST_DOCUMENT_START;
				} else
					throw new EmitterException("Expected 'stream start' but found: " + event);
			}
		};
		table[S_FIRST_DOCUMENT_START] = new EmitterState() {
			public void expect () throws IOException {
				if (event.type == DOCUMENT_START) {
					DocumentStartEvent documentStartEvent = (DocumentStartEvent)event;
					if (documentStartEvent.version != null) {
						if (documentStartEvent.version.major != 1)
							throw new EmitterException("Unsupported YAML version: " + documentStartEvent.version);
						writer.writeVersionDirective(documentStartEvent.version.toString());
					}
					if ((documentStartEvent.version != null && documentStartEvent.version.equals(1, 0)) || config.version.equals(1, 0)) {
						isVersion10 = true;
						tagPrefixes = new HashMap(DEFAULT_TAG_PREFIXES_1_0);
					} else
						tagPrefixes = new HashMap(DEFAULT_TAG_PREFIXES_1_1);

					if (documentStartEvent.tags != null) {
						Set<String> handles = new TreeSet();
						handles.addAll(documentStartEvent.tags.keySet());
						for (Iterator<String> iter = handles.iterator(); iter.hasNext();) {
							String handle = iter.next();
							String prefix = documentStartEvent.tags.get(handle);
							tagPrefixes.put(prefix, handle);
							String handleText = prepareTagHandle(handle);
							String prefixText = prepareTagPrefix(prefix);
							writer.writeTagDirective(handleText, prefixText);
						}
					}
				}
				expectDocumentStart(true);
			}
		};
		table[S_DOCUMENT_ROOT] = new EmitterState() {
			public void expect () throws IOException {
				states.add(0, S_DOCUMENT_END);
				expectNode(true, false, false, false);
			}
		};
		table[S_NOTHING] = new EmitterState() {
			public void expect () {
				throw new EmitterException("Expected no event but found: " + event);
			}
		};
		table[S_DOCUMENT_START] = new EmitterState() {
			public void expect () throws IOException {
				expectDocumentStart(false);
			}
		};
		table[S_DOCUMENT_END] = new EmitterState() {
			public void expect () throws IOException {
				if (event.type == DOCUMENT_END) {
					writer.writeIndent(indent);
					if (((DocumentEndEvent)event).isExplicit) {
						writer.writeIndicator("...", true, false, false);
						writer.writeIndent(indent);
					}
					writer.flushStream();
					state = S_DOCUMENT_START;
				} else
					throw new EmitterException("Expected 'document end' but found: " + event);
			}
		};
		table[S_FIRST_FLOW_SEQUENCE_ITEM] = new EmitterState() {
			public void expect () throws IOException {
				if (event.type == SEQUENCE_END) {
					indent = indents.remove(0);
					flowLevel--;
					writer.writeIndicator("]", false, false, false);
					state = states.remove(0);
				} else {
					if (config.canonical || writer.column > config.wrapColumn) writer.writeIndent(indent);
					states.add(0, S_FLOW_SEQUENCE_ITEM);
					expectNode(false, true, false, false);
				}
			}
		};
		table[S_FLOW_SEQUENCE_ITEM] = new EmitterState() {
			public void expect () throws IOException {
				if (event.type == SEQUENCE_END) {
					indent = indents.remove(0);
					flowLevel--;
					if (config.canonical) {
						writer.writeIndicator(",", false, false, false);
						writer.writeIndent(indent);
					}
					writer.writeIndicator("]", false, false, false);
					state = states.remove(0);
				} else {
					writer.writeIndicator(",", false, false, false);
					if (config.canonical || writer.column > config.wrapColumn) writer.writeIndent(indent);
					states.add(0, S_FLOW_SEQUENCE_ITEM);
					expectNode(false, true, false, false);
				}
			}
		};
		table[S_FIRST_FLOW_MAPPING_KEY] = new EmitterState() {
			public void expect () throws IOException {
				if (event.type == MAPPING_END) {
					indent = indents.remove(0);
					flowLevel--;
					writer.writeIndicator("}", false, false, false);
					state = states.remove(0);
				} else {
					if (config.canonical || writer.column > config.wrapColumn) writer.writeIndent(indent);
					if (!config.canonical && checkSimpleKey()) {
						states.add(0, S_FLOW_MAPPING_SIMPLE_VALUE);
						expectNode(false, false, true, true);
					} else {
						writer.writeIndicator("?", true, false, false);
						states.add(0, S_FLOW_MAPPING_VALUE);
						expectNode(false, false, true, false);
					}
				}
			}
		};
		table[S_FLOW_MAPPING_SIMPLE_VALUE] = new EmitterState() {
			public void expect () throws IOException {
				writer.writeIndicator(": ", false, true, false);
				states.add(0, S_FLOW_MAPPING_KEY);
				expectNode(false, false, true, false);
			}
		};
		table[S_FLOW_MAPPING_VALUE] = new EmitterState() {
			public void expect () throws IOException {
				if (config.canonical || writer.column > config.wrapColumn) writer.writeIndent(indent);
				writer.writeIndicator(": ", false, true, false);
				states.add(0, S_FLOW_MAPPING_KEY);
				expectNode(false, false, true, false);
			}
		};
		table[S_FLOW_MAPPING_KEY] = new EmitterState() {
			public void expect () throws IOException {
				if (event.type == MAPPING_END) {
					indent = indents.remove(0);
					flowLevel--;
					if (config.canonical) {
						writer.writeIndicator(",", false, false, false);
						writer.writeIndent(indent);
					}
					writer.writeIndicator("}", false, false, false);
					state = states.remove(0);
				} else {
					writer.writeIndicator(",", false, false, false);
					if (config.canonical || writer.column > config.wrapColumn) writer.writeIndent(indent);
					if (!config.canonical && checkSimpleKey()) {
						states.add(0, S_FLOW_MAPPING_SIMPLE_VALUE);
						expectNode(false, false, true, true);
					} else {
						writer.writeIndicator("?", true, false, false);
						states.add(0, S_FLOW_MAPPING_VALUE);
						expectNode(false, false, true, false);
					}
				}
			}
		};
		table[S_BLOCK_SEQUENCE_ITEM] = new EmitterState() {
			public void expect () throws IOException {
				expectBlockSequenceItem(false);
			}
		};
		table[S_FIRST_BLOCK_MAPPING_KEY] = new EmitterState() {
			public void expect () throws IOException {
				expectBlockMappingKey(true);
			}
		};
		table[S_BLOCK_MAPPING_SIMPLE_VALUE] = new EmitterState() {
			public void expect () throws IOException {
				writer.writeIndicator(": ", false, true, false);
				states.add(0, S_BLOCK_MAPPING_KEY);
				expectNode(false, false, true, false);
			}
		};
		table[S_BLOCK_MAPPING_VALUE] = new EmitterState() {
			public void expect () throws IOException {
				writer.writeIndent(indent);
				writer.writeIndicator(": ", true, true, true);
				states.add(0, S_BLOCK_MAPPING_KEY);
				expectNode(false, false, true, false);
			}
		};
		table[S_BLOCK_MAPPING_KEY] = new EmitterState() {
			public void expect () throws IOException {
				expectBlockMappingKey(false);
			}
		};
		table[S_FIRST_BLOCK_SEQUENCE_ITEM] = new EmitterState() {
			public void expect () throws IOException {
				expectBlockSequenceItem(true);
			}
		};
	}

	private void increaseIndent (boolean flow, boolean indentless) {
		indents.add(0, indent);
		if (indent == -1) {
			if (flow)
				indent = config.indentSize;
			else
				indent = 0;
		} else if (!indentless) indent += config.indentSize;
	}

	void expectDocumentStart (boolean first) throws IOException {
		if (event.type == DOCUMENT_START) {
			DocumentStartEvent ev = (DocumentStartEvent)event;
			boolean implicit = first && !ev.isExplicit && !config.canonical && ev.version == null && ev.tags == null
				&& !checkEmptyDocument();
			if (!implicit) {
				writer.writeIndent(indent);
				writer.writeIndicator("--- ", true, true, false);
				if (config.canonical) writer.writeIndent(indent);
			}
			state = S_DOCUMENT_ROOT;
		} else if (event.type == STREAM_END) {
			writer.writeStreamEnd();
			state = S_NOTHING;
		} else
			throw new EmitterException("Expected 'document start' but found: " + event);
	}

	void expectBlockSequenceItem (boolean first) throws IOException {
		if (!first && event.type == SEQUENCE_END) {
			indent = indents.remove(0);
			state = states.remove(0);
		} else {
			writer.writeIndent(indent);
			writer.writeIndicator("-", true, false, true);
			states.add(0, S_BLOCK_SEQUENCE_ITEM);
			expectNode(false, true, false, false);
		}
	}

	void expectBlockMappingKey (boolean first) throws IOException {
		if (!first && event.type == MAPPING_END) {
			indent = indents.remove(0);
			state = states.remove(0);
		} else {
			writer.writeIndent(indent);
			if (checkSimpleKey()) {
				states.add(0, S_BLOCK_MAPPING_SIMPLE_VALUE);
				expectNode(false, false, true, true);
			} else {
				writer.writeIndicator("?", true, false, true);
				states.add(0, S_BLOCK_MAPPING_VALUE);
				expectNode(false, false, true, false);
			}
		}
	}

	void expectNode (boolean root, boolean sequence, boolean mapping, boolean simpleKey) throws IOException {
		mappingContext = mapping;
		simpleKeyContext = simpleKey;
		if (event.type == ALIAS)
			expectAlias();
		else if (event.type == SCALAR || event.type == MAPPING_START || event.type == SEQUENCE_START) {
			processAnchor("&");
			processTag();
			if (event.type == SCALAR)
				expectScalar();
			else if (event.type == SEQUENCE_START) {
				if (flowLevel != 0 || config.canonical || ((SequenceStartEvent)event).isFlowStyle || checkEmptySequence())
					expectFlowSequence();
				else
					expectBlockSequence();
			} else if (event.type == MAPPING_START)
				if (flowLevel != 0 || config.canonical || ((MappingStartEvent)event).isFlowStyle || checkEmptyMapping())
					expectFlowMapping();
				else
					expectBlockMapping();
		} else
			throw new EmitterException("Expected 'scalar', 'mapping start', or 'sequence start' but found: " + event);
	}

	private void expectAlias () throws IOException {
		if (((NodeEvent)event).anchor == null) throw new EmitterException("Anchor is not specified for alias.");
		processAnchor("*");
		state = states.remove(0);
	}

	private void expectScalar () throws IOException {
		increaseIndent(true, false);
		processScalar();
		indent = indents.remove(0);
		state = states.remove(0);
	}

	private void expectFlowSequence () throws IOException {
		writer.writeIndicator("[", true, true, false);
		flowLevel++;
		increaseIndent(true, false);
		state = S_FIRST_FLOW_SEQUENCE_ITEM;
	}

	private void expectBlockSequence () {
		increaseIndent(false, mappingContext && !writer.indentation);
		state = S_FIRST_BLOCK_SEQUENCE_ITEM;
	}

	private void expectFlowMapping () throws IOException {
		writer.writeIndicator("{", true, true, false);
		flowLevel++;
		increaseIndent(true, false);
		state = S_FIRST_FLOW_MAPPING_KEY;
	}

	private void expectBlockMapping () {
		increaseIndent(false, false);
		state = S_FIRST_BLOCK_MAPPING_KEY;
	}

	private boolean checkEmptySequence () {
		return event.type == SEQUENCE_START && !events.isEmpty() && events.get(0).type == SEQUENCE_END;
	}

	private boolean checkEmptyMapping () {
		return event.type == MAPPING_START && !events.isEmpty() && events.get(0).type == MAPPING_END;
	}

	private boolean checkEmptyDocument () {
		if (event.type != DOCUMENT_START || events.isEmpty()) return false;
		Event ev = events.get(0);
		return ev.type == SCALAR && ((ScalarEvent)ev).anchor == null && ((ScalarEvent)ev).tag == null
			&& ((ScalarEvent)ev).implicit != null && ((ScalarEvent)ev).value.equals("");
	}

	boolean checkSimpleKey () {
		int length = 0;
		if (event instanceof NodeEvent && ((NodeEvent)event).anchor != null) {
			if (preparedAnchor == null) preparedAnchor = prepareAnchor(((NodeEvent)event).anchor);
			length += preparedAnchor.length();
		}
		String tag = null;
		if (event.type == SCALAR)
			tag = ((ScalarEvent)event).tag;
		else if (event.type == MAPPING_START || event.type == SEQUENCE_START) tag = ((CollectionStartEvent)event).tag;
		if (tag != null) {
			if (preparedTag == null) preparedTag = prepareTag(tag);
			length += preparedTag.length();
		}
		if (event.type == SCALAR && analysis == null) {
			analysis = ScalarAnalysis.analyze(((ScalarEvent)event).value, config.escapeUnicode);
			length += analysis.scalar.length();
		}

		return length < 128
			&& (event.type == ALIAS || event.type == SCALAR && !analysis.empty && !analysis.multiline || checkEmptySequence() || checkEmptyMapping());
	}

	private void processAnchor (String indicator) throws IOException {
		NodeEvent ev = (NodeEvent)event;
		if (ev.anchor == null) {
			preparedAnchor = null;
			return;
		}
		if (preparedAnchor == null) preparedAnchor = prepareAnchor(ev.anchor);
		if (preparedAnchor != null && !"".equals(preparedAnchor))
			writer.writeIndicator(indicator + preparedAnchor, true, false, false);
		preparedAnchor = null;
	}

	private void processTag () throws IOException {
		String tag = null;
		if (event.type == SCALAR) {
			ScalarEvent ev = (ScalarEvent)event;
			tag = ev.tag;
			if (style == 0) style = chooseScalarStyle();
			if ((!config.canonical || tag == null) && ((0 == style && ev.implicit[0]) || (0 != style && ev.implicit[1]))) {
				preparedTag = null;
				return;
			}
			if (ev.implicit[0] && tag == null) {
				tag = "!";
				preparedTag = null;
			}
		} else {
			CollectionStartEvent ev = (CollectionStartEvent)event;
			tag = ev.tag;
			if ((!config.canonical || tag == null) && ev.isImplicit) {
				preparedTag = null;
				return;
			}
		}
		if (tag == null) throw new EmitterException("Tag is not specified.");
		if (preparedTag == null) preparedTag = prepareTag(tag);
		if (preparedTag != null && !"".equals(preparedTag)) writer.writeIndicator(preparedTag, true, false, false);
		preparedTag = null;
	}

	private char chooseScalarStyle () {
		ScalarEvent ev = (ScalarEvent)event;
		if (analysis == null) analysis = ScalarAnalysis.analyze(ev.value, config.escapeUnicode);
		if (ev.style == '"' || config.canonical) return '"';
		if (ev.style == 0 && !(simpleKeyContext && (analysis.empty || analysis.multiline))
			&& (flowLevel != 0 && analysis.allowFlowPlain || flowLevel == 0 && analysis.allowBlockPlain)) return 0;
		if (ev.style == 0 && ev.implicit[0] && !(simpleKeyContext && (analysis.empty || analysis.multiline))
			&& (flowLevel != 0 && analysis.allowFlowPlain || flowLevel == 0 && analysis.allowBlockPlain)) return 0;
		if ((ev.style == '|' || ev.style == '>') && flowLevel == 0 && analysis.allowBlock) return '\'';
		if ((ev.style == 0 || ev.style == '\'') && analysis.allowSingleQuoted && !(simpleKeyContext && analysis.multiline))
			return '\'';
		if (ev.style == 0 && analysis.multiline && flowLevel == 0 && analysis.allowBlock) return '|';
		return '"';
	}

	private void processScalar () throws IOException {
		ScalarEvent ev = (ScalarEvent)event;
		if (analysis == null) analysis = ScalarAnalysis.analyze(ev.value, config.escapeUnicode);
		if (style == 0) style = chooseScalarStyle();
		boolean split = !simpleKeyContext;
		if (style == '"')
			writer.writeDoubleQuoted(analysis.scalar, split, indent, config.wrapColumn, config.escapeUnicode);
		else if (style == '\'')
			writer.writeSingleQuoted(analysis.scalar, split, indent, config.wrapColumn);
		else if (style == '>')
			writer.writeFolded(analysis.scalar, indent, config.wrapColumn);
		else if (style == '|')
			writer.writeLiteral(analysis.scalar, indent);
		else
			writer.writePlain(analysis.scalar, split, indent, config.wrapColumn);
		analysis = null;
		style = 0;
	}

	private String prepareTag (String tag) {
		if (tag == null || "".equals(tag)) throw new EmitterException("Tag cannot be empty.");
		if (tag.equals("!")) return tag;
		String handle = null;
		String suffix = tag;
		for (Iterator iter = tagPrefixes.keySet().iterator(); iter.hasNext();) {
			String prefix = (String)iter.next();
			if (tag.startsWith(prefix) && (prefix.equals("!") || prefix.length() < tag.length())) {
				handle = tagPrefixes.get(prefix);
				suffix = tag.substring(prefix.length());
			}
		}
		StringBuilder chunks = new StringBuilder();
		int start = 0, ending = 0;
		while (ending < suffix.length())
			ending++;
		if (start < ending) chunks.append(suffix.substring(start, ending));
		String suffixText = chunks.toString();
		if (tag.charAt(0) == '!' && isVersion10) return tag;
		if (handle != null) return handle + suffixText;
		if (config.useVerbatimTags)
			return "!<" + suffixText + ">";
		else
			return "!" + suffixText;
	}

	String prepareTagHandle (String handle) {
		if (handle == null || "".equals(handle))
			throw new EmitterException("Tag handle cannot be empty.");
		else if (handle.charAt(0) != '!' || handle.charAt(handle.length() - 1) != '!')
			throw new EmitterException("Tag handle must begin and end with '!': " + handle);
		else if (!"!".equals(handle) && !HANDLE_FORMAT.matcher(handle).matches())
			throw new EmitterException("Invalid syntax for tag handle: " + handle);
		return handle;
	}

	String prepareTagPrefix (String prefix) {
		if (prefix == null || "".equals(prefix)) throw new EmitterException("Tag prefix cannot be empty.");
		StringBuilder chunks = new StringBuilder();
		int start = 0, ending = 0;
		if (prefix.charAt(0) == '!') ending = 1;
		while (ending < prefix.length())
			ending++;
		if (start < ending) chunks.append(prefix.substring(start, ending));
		return chunks.toString();
	}

	private String prepareAnchor (String anchor) {
		if (anchor == null || "".equals(anchor)) throw new EmitterException("Anchor cannot be empty.");
		if (!ANCHOR_FORMAT.matcher(anchor).matches()) throw new EmitterException("Invalid syntax for anchor: " + anchor);
		return anchor;
	}

	private interface EmitterState {
		public void expect () throws IOException;
	}

	static private final int S_STREAM_START = 0;
	static private final int S_FIRST_DOCUMENT_START = 1;
	static private final int S_DOCUMENT_ROOT = 2;
	static private final int S_NOTHING = 3;
	static private final int S_DOCUMENT_START = 4;
	static private final int S_DOCUMENT_END = 5;
	static private final int S_FIRST_FLOW_SEQUENCE_ITEM = 6;
	static private final int S_FLOW_SEQUENCE_ITEM = 7;
	static private final int S_FIRST_FLOW_MAPPING_KEY = 8;
	static private final int S_FLOW_MAPPING_SIMPLE_VALUE = 9;
	static private final int S_FLOW_MAPPING_VALUE = 10;
	static private final int S_FLOW_MAPPING_KEY = 11;
	static private final int S_BLOCK_SEQUENCE_ITEM = 12;
	static private final int S_FIRST_BLOCK_MAPPING_KEY = 13;
	static private final int S_BLOCK_MAPPING_SIMPLE_VALUE = 14;
	static private final int S_BLOCK_MAPPING_VALUE = 15;
	static private final int S_BLOCK_MAPPING_KEY = 16;
	static private final int S_FIRST_BLOCK_SEQUENCE_ITEM = 17;

	static final Map<String, String> DEFAULT_TAG_PREFIXES_1_0 = new HashMap();
	static final Map<String, String> DEFAULT_TAG_PREFIXES_1_1 = new HashMap();
	static {
		DEFAULT_TAG_PREFIXES_1_0.put("tag:yaml.org,2002:", "!");

		DEFAULT_TAG_PREFIXES_1_1.put("!", "!");
		DEFAULT_TAG_PREFIXES_1_1.put("tag:yaml.org,2002:", "!!");
	}

	public static void main (String[] args) throws IOException {
		Parser parser = new Parser(new FileReader("test/test.yml"));
		Emitter emitter = new Emitter(new OutputStreamWriter(System.out));
		while (true) {
			Event event = parser.getNextEvent();
			if (event == null) break;
			emitter.emit(event);
		}
	}
}

redpajama_set_name: RedPajamaGithub


text:
import { Pills } from "../../";

export = Pills;


text:
// Global config
var GRAPHIC_DEFAULT_WIDTH = 600;
var MOBILE_THRESHOLD = 500;

// Global vars
var pymChild = null;
var isMobile = false;
var graphicData = null;

/*
 * Initialize the graphic.
 */
var onWindowLoaded = function() {
    if (Modernizr.svg) {
        loadLocalData(GRAPHIC_DATA);
        //loadCSV('data.csv')
    } else {
        pymChild = new pym.Child({});
    }
}

/*
 * Load graphic data from a local source.
 */
var loadLocalData = function(data) {
    graphicData = data;

    formatData();

    pymChild = new pym.Child({
        renderCallback: render
    });
}

/*
 * Load graphic data from a CSV.
 */
var loadCSV = function(url) {
    d3.csv(GRAPHIC_DATA_URL, function(error, data) {
        graphicData = data;

        formatData();

        pymChild = new pym.Child({
            renderCallback: render
        });
    });
}

/*
 * Format graphic data for processing by D3.
 */
var formatData = function() {
    graphicData.forEach(function(d) {
        d['key'] = d['Group'];
        d['values'] = [];

        _.each(d, function(v, k) {
            if (_.contains(['Group', 'key', 'values'], k)) {
                return;
            }

            d['values'].push({ 'label': k, 'amt': +v });
            delete d[k];
        });

        delete d['Group'];
    });
}

/*
 * Render the graphic(s). Called by pym with the container width.
 */
var render = function(containerWidth) {
    if (!containerWidth) {
        containerWidth = GRAPHIC_DEFAULT_WIDTH;
    }

    if (containerWidth <= MOBILE_THRESHOLD) {
        isMobile = true;
    } else {
        isMobile = false;
    }

    // Render the chart!
    renderGroupedBarChart({
        container: '#graphic',
        width: containerWidth,
        data: graphicData
    });

    // Update iframe
    if (pymChild) {
        pymChild.sendHeight();
    }
}

/*
 * Render a bar chart.
 */
var renderGroupedBarChart = function(config) {
    /*
     * Setup chart container.
     */
    var labelColumn = 'label';
    var valueColumn = 'amt';

    var numGroups = config['data'].length;
    var numGroupBars = config['data'][0]['values'].length;

    var barHeight = 25;
    var barGapInner = 2;
    var barGap = 10;
    var groupHeight =  (barHeight * numGroupBars) + (barGapInner * (numGroupBars - 1))
    var labelWidth = 85;
    var labelMargin = 6;
    var valueGap = 6;

    var margins = {
        top: 0,
        right: 15,
        bottom: 20,
        left: (labelWidth + labelMargin)
    };

    var ticksX = 7;
    var roundTicksFactor = 5;

    // Calculate actual chart dimensions
    var chartWidth = config['width'] - margins['left'] - margins['right'];
    var chartHeight = (((((barHeight + barGapInner) * numGroupBars) - barGapInner) + barGap) * numGroups) - barGap + barGapInner;

    // Clear existing graphic (for redraw)
    var containerElement = d3.select(config['container']);
    containerElement.html('');

    /*
     * Create D3 scale objects.
     */
    var min = d3.min(config['data'], function(d) {
        return d3.min(d['values'], function(v) {
            return Math.floor(v[valueColumn] / roundTicksFactor) * roundTicksFactor;
        });
    });

    if (min > 0) {
        min = 0;
    }

    var xScale = d3.scale.linear()
        .domain([
            min,
            d3.max(config['data'], function(d) {
                return d3.max(d['values'], function(v) {
                    return Math.ceil(v[valueColumn] / roundTicksFactor) * roundTicksFactor;
                });
            })
        ])
        .range([0, chartWidth]);

    var yScale = d3.scale.linear()
        .range([chartHeight, 0]);

    var colorScale = d3.scale.ordinal()
    .domain(_.pluck(config['data'][0]['values'], labelColumn))
        .range([COLORS['teal3'], COLORS['teal5']]);
    /*
     * Render a color legend.
     */
    var legend = containerElement.append('ul')
        .attr('class', 'key')
        .selectAll('g')
            .data(config['data'][0]['values'])
        .enter().append('li')
            .attr('class', function(d, i) {
                return 'key-item key-' + i + ' ' + classify(d[labelColumn]);
            });

    legend.append('b')
        .style('background-color', function(d) {
        	return colorScale(d[labelColumn]);
        });

    legend.append('label')
        .text(function(d) {
            return d[labelColumn];
        });

    /*
     * Create the root SVG element.
     */
    var chartWrapper = containerElement.append('div')
        .attr('class', 'graphic-wrapper');

    var chartElement = chartWrapper.append('svg')
        .attr('width', chartWidth + margins['left'] + margins['right'])
        .attr('height', chartHeight + margins['top'] + margins['bottom'])
        .append('g')
        .attr('transform', 'translate(' + margins['left'] + ',' + margins['top'] + ')');

    /*
     * Create D3 axes.
     */
    var xAxis = d3.svg.axis()
        .scale(xScale)
        .orient('bottom')
        .ticks(ticksX)
        .tickFormat(function(d) {
            return d.toFixed(0) + '%';
        });

    /*
     * Render axes to chart.
     */
    chartElement.append('g')
        .attr('class', 'x axis')
        .attr('transform', makeTranslate(0, chartHeight))
        .call(xAxis);

    /*
     * Render grid to chart.
     */
    var xAxisGrid = function() {
        return xAxis;
    };

    chartElement.append('g')
        .attr('class', 'x grid')
        .attr('transform', makeTranslate(0, chartHeight))
        .call(xAxisGrid()
            .tickSize(-chartHeight, 0, 0)
            .tickFormat('')
        );

    /*
     * Render bars to chart.
     */
    var barGroups = chartElement.selectAll('.bars')
        .data(config['data'])
        .enter()
        .append('g')
            .attr('class', 'g bars')
            .attr('transform', function(d, i) {
                if (i == 0) {
                    return makeTranslate(0, 0);
                }

                return makeTranslate(0, (groupHeight + barGap) * i);
            });

    barGroups.selectAll('rect')
        .data(function(d) {
            return d['values'];
        })
        .enter()
        .append('rect')
            .attr('x', function(d) {
                if (d[valueColumn] >= 0) {
                    return xScale(0);
                }

                return xScale(d[valueColumn]);
            })
            .attr('y', function(d, i) {
                if (i == 0) {
                    return 0;
                }

                return (barHeight * i) + (barGapInner * i);
            })
            .attr('width', function(d) {
                return Math.abs(xScale(0) - xScale(d[valueColumn]));
            })
            .attr('height', barHeight)
            .style('fill', function(d) {
            	return colorScale(d[labelColumn]);
            })
            .attr('class', function(d) {
                return 'y-' + d[labelColumn];
            });

    /*
     * Render bar labels.
     */
    chartWrapper.append('ul')
        .attr('class', 'labels')
        .attr('style', formatStyle({
            'width': labelWidth + 'px',
            'top': margins['top'] + 'px',
            'left': '0'
        }))
        .selectAll('li')
        .data(config['data'])
        .enter()
        .append('li')
            .attr('style', function(d,i) {
                var top = (groupHeight + barGap) * i;

                if (i == 0) {
                    top = 0;
                }

                return formatStyle({
                    'width': (labelWidth - 10) + 'px',
                    'height': barHeight + 'px',
                    'left': '0px',
                    'top': top + 'px;'
                });
            })
            .attr('class', function(d,i) {
                return classify(d['key']);
            })
            .append('span')
                .text(function(d) {
                    return d['key']
                });

    /*
     * Render bar values.
     */
    barGroups.append('g')
        .attr('class', 'value')
        .selectAll('text')
        .data(function(d) {
            return d['values'];
        })
        .enter()
        .append('text')
            .text(function(d) {
                var v = d[valueColumn].toFixed(0);

                if (d[valueColumn] > 0 && v == 0) {
                    v = '<1';
                }

                return v + '%';
            })
            .attr('x', function(d) {
                return xScale(d[valueColumn]);
            })
            .attr('y', function(d, i) {
                if (i == 0) {
                    return 0;
                }

                return (barHeight * i) + barGapInner;
            })
            .attr('dx', function(d) {
                var xStart = xScale(d[valueColumn]);
                var textWidth = this.getComputedTextLength()

                // Negative case
                if (d[valueColumn] < 0) {
                    var outsideOffset = -(valueGap + textWidth);

                    if (xStart + outsideOffset < 0) {
                        d3.select(this).classed('in', true)
                        return valueGap;
                    } else {
                        d3.select(this).classed('out', true)
                        return outsideOffset;
                    }
                // Positive case
                } else {
                    if (xStart + valueGap + textWidth > chartWidth) {
                        d3.select(this).classed('in', true)
                        return -(valueGap + textWidth);
                    } else {
                        d3.select(this).classed('out', true)
                        return valueGap;
                    }
                }
            })
            .attr('dy', (barHeight / 2) + 4);
}

/*
 * Initially load the graphic
 * (NB: Use window.load to ensure all images have loaded)
 */
window.onload = onWindowLoaded;


text:
<TEMPLATE ID="suv" FORMAT="WRAPPER">

<ELEMENT ID="CPULWIA" SUB="LINK_VISITED_TEXT_COLOR" TYPE="READONLY" LOAD="THEME::LINK_VISITED_TEXT_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIB" SUB="TABLE_HEADING_FONT_SIZE" TYPE="READONLY" LOAD="THEME::TABLE_HEADING_FONT_SIZE" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIC" SUB="DISCLAIMER_FONT_SIZE" TYPE="READONLY" LOAD="THEME::DISCLAIMER_FONT_SIZE" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWID" SUB="CONTENT_BACKGROUND_COLOR" TYPE="READONLY" LOAD="THEME::CONTENT_BACKGROUND_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIE" SUB="TABLE_LISTING_BACKGROUND_COLOR" TYPE="READONLY" LOAD="THEME::TABLE_LISTING_BACKGROUND_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIF" SUB="CONTENT_TEXT_COLOR" TYPE="READONLY" LOAD="THEME::CONTENT_TEXT_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIG" SUB="TABLE_LISTING_FONT_SIZE" TYPE="READONLY" LOAD="THEME::TABLE_LISTING_FONT_SIZE" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIH" SUB="TABLE_LISTING_TEXT_COLOR" TYPE="READONLY" LOAD="THEME::TABLE_LISTING_TEXT_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWII" SUB="TABLE_LISTING_FONT_FACE" TYPE="READONLY" LOAD="THEME::TABLE_LISTING_FONT_FACE" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIJ" SUB="CONTENT_FONT_FACE" TYPE="READONLY" LOAD="THEME::CONTENT_FONT_FACE" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIK" SUB="NAME" TYPE="READONLY" LOAD="THEME::NAME" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIL" SUB="DISCLAIMER_FONT_FACE" TYPE="READONLY" LOAD="THEME::DISCLAIMER_FONT_FACE" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIM" SUB="PRETTY_NAME" TYPE="READONLY" LOAD="THEME::PRETTY_NAME" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIN" SUB="TABLE_HEADING_BACKGROUND_COLOR" TYPE="READONLY" LOAD="THEME::TABLE_HEADING_BACKGROUND_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIO" SUB="TABLE_LISTING_BACKGROUND_COLOR_ALTERNATE" TYPE="READONLY" LOAD="THEME::TABLE_LISTING_BACKGROUND_COLOR_ALTERNATE" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIP" SUB="LINK_ACTIVE_TEXT_COLOR" TYPE="READONLY" LOAD="THEME::LINK_ACTIVE_TEXT_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIQ" SUB="CONTENT_FONT_SIZE" TYPE="READONLY" LOAD="THEME::CONTENT_FONT_SIZE" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIR" SUB="ALERT_COLOR" TYPE="READONLY" LOAD="THEME::ALERT_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIS" SUB="DISCLAIMER_BACKGROUND_COLOR" TYPE="READONLY" LOAD="THEME::DISCLAIMER_BACKGROUND_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIT" SUB="TABLE_HEADING_FONT_FACE" TYPE="READONLY" LOAD="THEME::TABLE_HEADING_FONT_FACE" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIU" SUB="TABLE_HEADING_TEXT_COLOR" TYPE="READONLY" LOAD="THEME::TABLE_HEADING_TEXT_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIV" SUB="DISCLAIMER_TEXT_COLOR" TYPE="READONLY" LOAD="THEME::DISCLAIMER_TEXT_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIW" SUB="LINK_TEXT_COLOR" TYPE="READONLY" LOAD="THEME::LINK_TEXT_COLOR" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIX" SUB="HOMECATEGORY_URL" TYPE="READONLY" LOAD="URL::HOMECATEGORY_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIY" SUB="WRAPPER_URL" TYPE="READONLY" LOAD="URL::WRAPPER_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWIZ" SUB="CART_URL" TYPE="READONLY" LOAD="URL::CART_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJA" SUB="SUBSCRIBE_URL" TYPE="READONLY" LOAD="URL::SUBSCRIBE_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJB" SUB="FEEDBACK_URL" TYPE="READONLY" LOAD="URL::FEEDBACK_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJC" SUB="LOGOUT_FUNCTION_URL" TYPE="READONLY" LOAD="URL::LOGOUT_FUNCTION_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJD" SUB="SHIPQUOTE_URL" TYPE="READONLY" LOAD="URL::SHIPQUOTE_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJE" SUB="PRIVACY_URL" TYPE="READONLY" LOAD="URL::PRIVACY_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJF" SUB="SITEBUTTON_URL" TYPE="READONLY" LOAD="URL::SITEBUTTON_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJG" SUB="HOMEPAGE_URL" TYPE="READONLY" LOAD="URL::HOMEPAGE_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJH" SUB="COUNTER_URL" TYPE="READONLY" LOAD="URL::COUNTER_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJI" SUB="RETURNS_URL" TYPE="READONLY" LOAD="URL::RETURNS_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJJ" SUB="PASSWORD_URL" TYPE="READONLY" LOAD="URL::PASSWORD_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJK" SUB="UPDATE_PAYMENT_URL" TYPE="READONLY" LOAD="URL::UPDATE_PAYMENT_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJL" SUB="FORGOT_URL" TYPE="READONLY" LOAD="URL::FORGOT_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJM" SUB="NAVBUTTON_URL" TYPE="READONLY" LOAD="URL::NAVBUTTON_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJN" SUB="CONTACT_URL" TYPE="READONLY" LOAD="URL::CONTACT_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJO" SUB="LOGOUT_URL" TYPE="READONLY" LOAD="URL::LOGOUT_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJP" SUB="GALLERY_URL" TYPE="READONLY" LOAD="URL::GALLERY_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJQ" SUB="REMOVE_URL" TYPE="READONLY" LOAD="URL::REMOVE_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJR" SUB="HOME_URL" TYPE="READONLY" LOAD="URL::HOME_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJS" SUB="ABOUT_ZOOVY_URL" TYPE="READONLY" LOAD="URL::ABOUT_ZOOVY_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJT" SUB="NEWS_URL" TYPE="READONLY" LOAD="URL::NEWS_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJU" SUB="SECURE_URL" TYPE="READONLY" LOAD="URL::SECURE_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJV" SUB="ABOUT_URL" TYPE="READONLY" LOAD="URL::ABOUT_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJW" SUB="USERBUTTON_URL" TYPE="READONLY" LOAD="URL::USERBUTTON_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJX" SUB="CLOSED_URL" TYPE="READONLY" LOAD="URL::CLOSED_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJY" SUB="FASTORDER_URL" TYPE="READONLY" LOAD="URL::FASTORDER_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWJZ" SUB="MAIL_FORM_URL" TYPE="READONLY" LOAD="URL::MAIL_FORM_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKA" SUB="GRAPHICS_URL" TYPE="READONLY" LOAD="URL::GRAPHICS_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKB" SUB="IMAGE_URL" TYPE="READONLY" LOAD="URL::IMAGE_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKC" SUB="CONTACTUS_URL" TYPE="READONLY" LOAD="URL::CONTACTUS_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKD" SUB="DYNAMIC_URL" TYPE="READONLY" LOAD="URL::DYNAMIC_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKE" SUB="NONSECURE_URL" TYPE="READONLY" LOAD="URL::NONSECURE_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKF" SUB="CONTACT_US_URL" TYPE="READONLY" LOAD="URL::CONTACT_US_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKG" SUB="SEARCH_URL" TYPE="READONLY" LOAD="URL::SEARCH_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKH" SUB="ABOUTUS_URL" TYPE="READONLY" LOAD="URL::ABOUTUS_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKI" SUB="CUSTOMER_MAIN_URL" TYPE="READONLY" LOAD="URL::CUSTOMER_MAIN_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKJ" SUB="MERCHANT_LOGIN_URL" TYPE="READONLY" LOAD="URL::MERCHANT_LOGIN_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKK" SUB="CATEGORY_URL" TYPE="READONLY" LOAD="URL::CATEGORY_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKL" SUB="ADULT_URL" TYPE="READONLY" LOAD="URL::ADULT_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKM" SUB="CLAIM_URL" TYPE="READONLY" LOAD="URL::CLAIM_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKN" SUB="CLAIM_MULTI_URL" TYPE="READONLY" LOAD="URL::CLAIM_MULTI_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKO" SUB="ABOUT_US_URL" TYPE="READONLY" LOAD="URL::ABOUT_US_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKP" SUB="RESULTS_URL" TYPE="READONLY" LOAD="URL::RESULTS_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKQ" SUB="PRODUCT_URL" TYPE="READONLY" LOAD="URL::PRODUCT_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKR" SUB="CONTINUE_URL" TYPE="READONLY" LOAD="URL::CONTINUE_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKS" SUB="REDIR_URL" TYPE="READONLY" LOAD="URL::REDIR_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKT" SUB="KILL_COOKIES_URL" TYPE="READONLY" LOAD="URL::KILL_COOKIES_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKU" SUB="LOGIN_URL" TYPE="READONLY" LOAD="URL::LOGIN_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKV" SUB="CHECKOUT_URL" TYPE="READONLY" LOAD="URL::CHECKOUT_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKW" SUB="ORDER_STATUS_URL" TYPE="READONLY" LOAD="URL::ORDER_STATUS_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKX" SUB="NO_COOKIES_URL" TYPE="READONLY" LOAD="URL::NO_COOKIES_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKY" SUB="PAYPAL_URL" TYPE="READONLY" LOAD="URL::PAYPAL_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWKZ" SUB="CANCEL_ORDER_URL" TYPE="READONLY" LOAD="URL::CANCEL_ORDER_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWLA" SUB="MAIL_CONFIG_URL" TYPE="READONLY" LOAD="URL::MAIL_CONFIG_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWLB" SUB="DISABLED_URL" TYPE="READONLY" LOAD="URL::DISABLED_URL" RAW="1"></ELEMENT>
<ELEMENT ID="CPULWLC" TYPE="OUTPUT"><![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
]]>
</ELEMENT>
<ELEMENT ID="CPULWLD" COLORS="128" TYPE="CONFIG" CATEGORIES="32896" CREATED="20021223" TITLE="S.U.V." PROPERTIES="8"><CSS><![CDATA[.zbody {  background-color: #FFFFFF; }
.zborder {  border: 1px solid #CCCCCC; }
.zbox {  border: 1px solid #990000; }
.zbox_body {  background-color: #FFFFFF; color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.zbox_head {  background-color: #990000; color: #FFFFFF; font-family: Arial, Helvetica; font-size: 9pt; }
.zcolor {  background-color: #990000; color: #ffffff; }
.zcolor_contrast {  background-color: #997575; color: #101010; }
.zcolor_dark {  background-color: #590000; color: #bfbfbf; }
.zcolor_light {  background-color: #d94040; color: #ffffff; }
.zform_button {  background-color: #d94040; border: 1px solid #590000; color: #590000; font-family: Arial, Helvetica; font-size: 8pt; }
.zform_select {  background-color: #FFFFFF; border: 1px solid #590000; color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.zform_textarea {  background-color: #FFFFFF; border: 1px solid #590000; color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.zform_textbox {  background-color: #FFFFFF; border: 1px solid #590000; color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.zhint {  color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.zlink {  color: #990000; }
.zsmall {  color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.ztab0 {  background-color: #ffffd9; color: #404040; font-family: Arial, Helvetica; font-size: 9pt; }
.ztab1 {  background-color: #FFFFFF; color: #000000; font-family: Arial, Helvetica; font-size: 9pt; font-weight: bold; }
.ztabbody {  background-color: #990000; color: #FFFFFF; font-family: Arial, Helvetica; font-size: 8pt; }
.ztable_head {  background-color: #990000; color: #FFFFFF; font-family: Arial, Helvetica; font-size: 9pt; }
.ztable_row {  color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.ztable_row0 {  background-color: #FFFFFF; color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.ztable_row1 {  background-color: #CCCC99; color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.ztable_row_small {  color: #000000; font-family: Arial, Helvetica; font-size: 8pt; }
.ztable_row_title {  color: #000000; font-family: Arial, Helvetica; font-size: 11pt; font-weight: bold; }
.ztitle {  color: #000000; font-family: Arial, Helvetica; font-size: 10pt; font-weight: bold; }
.ztitle2 {  color: #000000; font-family: Arial, Helvetica; font-size: 9pt; font-weight: bold; }
.ztxt {  color: #000000; font-family: Arial, Helvetica; font-size: 9pt; }
.zwarn {  color: #990000; font-weight: bold; }
]]></CSS>
<THEME><![CDATA[alert_color=990000&content_background_color=FFFFFF&content_font_face=Arial%2c+Helvetica&content_font_size=2&content_text_color=000000&disclaimer_background_color=FFFFFF&disclaimer_font_face=Arial%2c+Helvetica&disclaimer_font_size=1&disclaimer_text_color=000000&link_active_text_color=990000&link_text_color=990000&link_visited_text_color=990000&name=&pretty_name=&table_heading_background_color=990000&table_heading_font_face=Arial%2c+Helvetica&table_heading_font_size=2&table_heading_text_color=FFFFFF&table_listing_background_color=FFFFFF&table_listing_background_color_alternate=CCCC99&table_listing_font_face=Arial%2c+Helvetica&table_listing_font_size=1&table_listing_text_color=000000]]></THEME>
<THEME_OLD><![CDATA[disclaimer_text_color=CCCC99&content_font_face=Arial%2c+Helvetica&table_listing_background_color_alternate=CCCC99&table_heading_text_color=FFFFFF&pretty_name=suv&link_visited_text_color=990000&content_background_color=FFFFFF&table_heading_background_color=990000&link_text_color=990000&link_active_text_color=990000&table_listing_font_face=Arial%2c+Helvetica&content_text_color=000000&content_font_size=2&disclaimer_font_face=Arial%2c+Helvetica&name=suv&table_listing_background_color=FFFFFF&disclaimer_background_color=990000&alert_color=990000&disclaimer_font_size=1&table_listing_text_color=000000&table_heading_font_face=Arial%2c+Helvetica&table_heading_font_size=2&table_listing_font_size=1]]></THEME_OLD>
<SITEBUTTONS><![CDATA[forward=lucido|gif|45|15&add_to_cart=lucido|gif|61|15&back=lucido|gif|52|15&default=lucido|gif|65|15&checkout=lucido|gif|52|15&continue_shopping=lucido|gif|74|15&add_to_site_height=32&update_cart=lucido|gif|65|15Add+To+Site+Width&cancel=lucido|gif|38|15]]></SITEBUTTONS>
</ELEMENT>
<ELEMENT ID="CPULWLE" TYPE="OUTPUT"><![CDATA[

]]>
</ELEMENT>
<ELEMENT ID="CPULWLF" TYPE="HEAD"></ELEMENT>
<ELEMENT ID="CPULWLG" TYPE="OUTPUT"><![CDATA[

					]]>
</ELEMENT>
<ELEMENT HEIGHT="89" ID="CPULWLH" WIDTH="500" TYPE="LOGO"></ELEMENT>
<ELEMENT ID="CPULWLI" TYPE="OUTPUT"><![CDATA[

					<form action="%RESULTS_URL%" method="get"><input type="hidden" name="catalog" value=""><input type="text" name="keywords" value="" size="10" maxlength="25" style="border-color:#990000; background-color:#ffffff; color:#666666; font-family: sans-serif; font-size: 12px; width: 100px"> <input type="image" src="%WRAPPER_URL%/search.gif" border=0></form>

								 Home

								 Cart

								 Company Info

								 Contact Us

]]>
</ELEMENT>
<ELEMENT ID="CPULWLJ" NOHOME="1" TYPE="MENU" ONLYHOME="0"><![CDATA[

  <a href="<% load($cat_url);  default("");  print(); %>" target="<% load($TARGET);  default("");  print(); %>"><% load($cat_pretty);  default("");  print(); %>

]]>
</ELEMENT>
<ELEMENT ID="CPULWLK" TYPE="OUTPUT"><![CDATA[

]]>
</ELEMENT>
<ELEMENT ID="CPULWLL" TYPE="TITLE"></ELEMENT>
<ELEMENT ID="CPULWLM" TYPE="OUTPUT"><![CDATA[
]]>
</ELEMENT>
<ELEMENT ID="CPULWLN" TYPE="BODY"></ELEMENT>
<ELEMENT ID="CPULWLO" TYPE="OUTPUT"><![CDATA[

					]]>
</ELEMENT>
<ELEMENT ID="CPULWLP" TYPE="FOOTER" TRANSPARENT="TRUE"></ELEMENT>
<ELEMENT ID="CPULWLQ" TYPE="OUTPUT"><![CDATA[

]]>
</ELEMENT>

</TEMPLATE>


text:
jstestdriver --config Bookmarks.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config bugs.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config common.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config Daisy202Loader.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config javascript-stacktrace.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config jQueryMobile.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config log4javascript.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config NLBServer.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config SmilPlayer.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config SmilPlayerUI.conf --tests all --captureConsole --testOutput %~dp0\results
jstestdriver --config soundmanager2.conf --tests all --captureConsole --testOutput %~dp0\results


text:
import React from 'react'
import { update, destroy } from 'client/actions/todoActions'

export default class TodoItem extends React.Component {

	toggleTodo() {
		const { todo } = this.props
		const updatedTodo = {...todo, is_completed: !Boolean(todo.is_completed)}

		update(updatedTodo)
	}

	render() {
		const { id, text, is_completed } = this.props.todo
		const clazz = `bb-todo-item${is_completed ? ' bb-todo-item--done' : ''}`

		return (

 this.toggleTodo()}>{ text }

		);
	}
}


text:
'use strict';

angular.module('sidebars').directive('sidebarMain', [
	function() {
		return {
			templateUrl: 'modules/sidebars/views/sidebar-main.client.view.html',
			restrict: 'E',
			link: function postLink(scope, element, attrs) {

			}
		};
	}
]);


text:
namespace UnityEngine
{
    public static class MathExtension
    {
        public static float SnapToCenter(this float val, float snapValue)
        {
            if (snapValue == 0) return val;

            return Mathf.Round((val / snapValue) + 0.5f) * snapValue - 0.5f;
        }

        public static float SnapToEdge(this float val, float snapValue)
        {
            if (snapValue == 0) return val;

            return Mathf.Round(val / snapValue) * snapValue;
        }

        public static Vector3 SnapToCenter(this Vector2 val, float snapValue)
        {
            return new Vector2(val.x.SnapToCenter(snapValue), val.y.SnapToCenter(snapValue));
        }

        public static Vector3 SnapToEdge(this Vector2 val, float snapValue)
        {
            return new Vector2(val.x.SnapToEdge(snapValue), val.y.SnapToEdge(snapValue));
        }

        public static Vector3 SnapToCenter(this Vector3 val, float snapValue)
        {
            return new Vector3(val.x.SnapToCenter(snapValue), val.y.SnapToCenter(snapValue), val.z.SnapToCenter(snapValue));
        }

        public static Vector3 SnapToEdge(this Vector3 val, float snapValue)
        {
            return new Vector3(val.x.SnapToEdge(snapValue), val.y.SnapToEdge(snapValue), val.z.SnapToEdge(snapValue));
        }

        public static Vector3 ToVector3XZ(this Vector2 val)
        {
            return new Vector3(val.x, 0.0f, val.y);
        }

        public static float ClosestPointDistance(this Ray val, Vector3 point)
        {
            return Vector3.Dot(point - val.origin, val.direction);
        }

        public static Vector3 ClosestPoint(this Ray val, Vector3 point)
        {
            return val.GetPoint(val.ClosestPointDistance(point));
        }

        public static float ClosestRayPointDistance(this Ray val, Ray ray)
        {
            Vector3 v0 = val.origin;
            Vector3 v1 = val.direction;
            Vector3 v2 = ray.origin;
            Vector3 v3 = ray.direction;
            Vector3 v4 = v0 - v2;

            float d0 = 0.0f;
            float d1 = 0.0f;

            float dv4v3 = Vector3.Dot(v4, v3);
            float dv3v1 = Vector3.Dot(v3, v1);
            float dv3v3 = Vector3.Dot(v3, v3);
            float dv4v1 = Vector3.Dot(v4, v1);
            float dv1v1 = Vector3.Dot(v1, v1);

            float denom = dv1v1 * dv3v3 - dv3v1 * dv3v1;

            if (Mathf.Abs(denom) > Mathf.Epsilon)
            {
                float numer = dv4v3 * dv3v1 - dv4v1 * dv3v3;
                d0 = numer / denom;
            }
            else
            {
                d0 = 0.0f;
            }

            d1 = (dv4v3 + d0 * dv3v1) / dv3v3;

            if (d1 >= 0.0f)
            {
                return d0;
            }
            else
            {
                d1 = 0.0f;

                return val.ClosestPointDistance(ray.origin);
            }
        }

        public static Vector3 ClosestRayPoint(this Ray val, Ray ray)
        {
            return val.GetPoint(val.ClosestRayPointDistance(ray));
        }

        public static int Mod(this int val, int mod)
        {
            int r = val % mod;

            return r < 0 ? val + mod : r;
        }

        public static bool PlaneTest(this Ray ray, Vector3 planeCenter, Quaternion planeRot, Vector2 planeSize, out Vector3 hitPosition, float gridSize = 0.0f, bool edge = true)
        {
            Plane plane = new Plane(planeRot * Vector3.up, planeCenter);

            hitPosition = Vector3.zero;
            float hitDistance = 0.0f;

            if (!plane.Raycast(ray, out hitDistance))
            {
                return false;
            }

            hitPosition = ray.origin + ray.direction * hitDistance;

            Vector3 hitOffset = hitPosition - planeCenter;

            float distanceLf = Vector3.Dot(hitOffset, planeRot * Vector3.left);
            float distanceUp = Vector3.Dot(hitOffset, planeRot * Vector3.forward);

            if (gridSize > 0.0f)
            {
                if (edge)
                {
                    distanceLf = distanceLf.SnapToEdge(gridSize);
                    distanceUp = distanceUp.SnapToEdge(gridSize);
                }
                else
                {
                    distanceLf = distanceLf.SnapToCenter(gridSize);
                    distanceUp = distanceUp.SnapToCenter(gridSize);
                }
            }

            hitPosition = planeCenter;
            hitPosition += (planeRot * Vector3.left) * distanceLf;
            hitPosition += (planeRot * Vector3.forward) * distanceUp;

            return true;
        }

        public static float NormalizeAngle(this float ang)
        {
            return ang - Mathf.Floor((ang + 180f) / 360f) * 360f;
        }

        public static float AngleDiff(this float ang, float other)
        {
            return (other - ang).NormalizeAngle();
        }
    }
}


text:
require 'fileutils'

module MasterFileManagementJobs
  class Move < ActiveJob::Base
    queue_as :master_file_management_move

    def s3_to_s3(source, dest)
      source_object = FileLocator::S3File.new(source.source).object
      dest_object = FileLocator::S3File.new(dest.source).object
      if dest_object.copy_from(source_object, multipart_copy: source_object.size > 15.megabytes)
        source_object.delete if FileLocator.new(dest.source).exists?
      end
    end

    def s3_to_file(source, dest)
      source_object = FileLocator::S3File.new(source.source).object
      FileUtils.mkdir_p File.dirname(dest.uri.path) unless File.exist? File.dirname(dest.uri.path)
      if source_object.download_file(dest.uri.path)
        source_object.delete
      end
    end

    def file_to_s3(source, dest)
      dest_object = FileLocator::S3File.new(dest.source).object
      if dest_object.upload_file(source.uri.path)
        FileUtils.rm(source.uri.path)
      end
    end

    def file_to_file(source, dest)
    	FileUtils.mkdir_p File.dirname(dest.location) unless File.exist? File.dirname(dest.location)
    	FileUtils.mv source.location, dest.location
    end

    def perform(id, newpath)
      Rails.logger.debug "Moving masterfile to #{newpath}"

      masterfile = MasterFile.find(id)
      oldpath = masterfile.file_location
      old_locator = FileLocator.new(oldpath)

      if newpath == oldpath
        Rails.logger.info "Masterfile #{newpath} already moved"
      elsif old_locator.exists?
        new_locator = FileLocator.new(newpath)
        copy_method = "#{old_locator.uri.scheme}_to_#{new_locator.uri.scheme}".to_sym
        send(copy_method, old_locator, new_locator)
        masterfile.file_location = newpath
      	masterfile.save
        Rails.logger.info "#{oldpath} has been moved to #{newpath}"
      else
        Rails.logger.error "MasterFile #{oldpath} does not exist"
      end
    end
  end

  class Delete < ActiveJob::Base
    queue_as :master_file_management_delete
    def perform(id)
      Rails.logger.debug "Deleting masterfile"

      masterfile = MasterFile.find(id)
      oldpath = masterfile.file_location
      locator = FileLocator.new(oldpath)
      if locator.exists?
        case locator.uri.scheme
        when 'file' then File.delete(oldpath)
        when 's3'   then FileLocator::S3File.new(locator.source).object.delete
        end
      	masterfile.file_location = ""
      	masterfile.save
      	Rails.logger.info "#{oldpath} has been deleted"
      else
      	unless masterfile.file_location.empty?
      	  masterfile.file_location = ""
      	  masterfile.save
      	end
      	Rails.logger.warn "MasterFile #{oldpath} does not exist"
      end
    end
  end
end


text:
include("${CMAKE_CURRENT_LIST_DIR}/trace_versionTargets.cmake")

get_filename_component(trace_version_INCLUDE_DIRS "${SELF_DIR}/../../include/trace_version" ABSOLUTE)
set(trace_version_LIBRARIES trace_version)


text:
This repository contains the source code of the libraries used in [Windows App Studio](http://appstudio.windows.com) to create our generated apps.

A sample implementation of these libraries is available in the Windows Store: [Windows App Studio Uwp Samples](https://www.microsoft.com/en-us/store/apps/windows-app-studio-uwp-samples/9nblggh4r0w1). You can see the implementation details in the [source code](https://github.com/wasteam/waslibs/tree/master/samples).

There are three libraries: DataProviders, Uwp and Common. The libraries are also available as Nuget packages.
```
https://www.nuget.org/packages/WindowsAppStudio.Uwp
https://www.nuget.org/packages/WindowsAppStudio.DataProviders
https://www.nuget.org/packages/WindowsAppStudio.Common
```
# Table of Contents
- [Uwp Library](#uwp)
    - [Layout Controls](#layout-controls)
        - [ResponsiveGridView](#responsive-grid-view)
        - [Pivorama](#pivorama)
        - [VariableSizedGrid](#variable-sized-grid)
        - [Carousel](#carousel)
        - [SliderView](#slider-view)
        - [SectionList](#section-list)
        - [SplitterCard](#splitter-card)
    - [Foundation Controls](#foundation-controls)
        - [HtmlBlock](#html-block)
        - [VisualBreakpoints](#visual-breakpoints)
        - [ImageEx](#image-ex)
        - [GifControl](#gif-control)
        - [VirtualBox](#virtual-box)
        - [RelativeBox](#relative-box)
        - [RelativeBox and VirtualBox](#relative-and-virtual-box)
        - [SearchBox](#search-box)
        - [InfiniteScroll](#infinite-scroll)
    - [App Services](#app-services)
        - [Navigation](#navigation)
        - [AppCache](#appcache)
    - [Utilities](#utilities)
        - [ErrorNotification](#error-notification)
        - [ActionsCommandBar](#actions-command-bar)
        - [AnimationExtensions](#animation-extensions)
        - [Converters](#converters)
    - [Labs](#labs)
        - [ResponsiveGridView](#responsive-grid-view-labs)
        - [Accordion](#accordion)
        - [SlideShow](#slide-show)
        - [ShapeImage](#shape-image)
        - [AutoHide](#auto-hide)
        - [Mosaic](#mosaic)
- [Data Providers Library](#data-providers)
    - [Facebook](#facebook)
    - [Twitter](#twitter)
    - [Flickr](#flickr)
    - [YouTube](#youtube)
    - [WordPress](#wordpress)
    - [Rss](#rss)
    - [Bing](#bing)
    - [LocalStorage](#local-storage)
    - [REST API](#rest-api)
- [Common](#common)

# Uwp Library
This library contains XAML controls for Windows 10 apps **only**.

##Layout Controls
###ResponsiveGridView Control
The ResponsiveGridView control allows to present information within a Grid View perfectly adjusting the total display available space. It reacts to changes in the layout as well as the content so it can adapt to different form factors automatically. The number and the width of items are calculated based on the screen resolution in order to fully leverage the available screen space. The property ItemsHeight define the items fixed height and the property DesiredWidth sets the minimum width for the elements to add a new column.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/ResponsiveGridView

###Pivorama Control
The Pivorama control allows to visualize a set of elements optimizing the available space to display them. The Pivorama behaves differently based on the screen size: in big screens, it maximizes the number of items displayed using a table kind layout, with the ability to slide horizontally; in small screens, it behaves more like a Pivot control, showing the items in groups, with a heading inviting to slide horizontally. The Pivorama control is ideal to display big number of items in the best way depending on the device form factor.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/Pivorama

###VariableSizedGrid Control
The VariableSizedGrid control allows to display items from a list using different values for Width and Height item properties. You can control the number of rows and columns to be displayed as well as the items orientation in the panel. Finally, the AspectRatio property allow us to control the relation between Width and Height.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/VariableSizedGrid

###Carousel Control
The Carousel offer an alternative to image visualization adding horizontal scroll to a set of items. The Carousel control is responsive by design, optimizing the image visualization in the different form factors. You can control properties like the AspectRatio, MaxItems, MinHeight, MaxHeight, GradientOpacity and AlignmentX to properly behave depending on the resolution and space available.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/Carousel

###SliderView Control
The SliderView control displays a set of images in horizontal layout allowing the user to slide one by one image horizontally. The SliderView control is responsive by design and you can control images the Height and Width as well as optionally decide if you want to show arrows or not to slide the images.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/SliderView

###SectionList Control
The SectionList control enables the horizontal item visualization adjusting the number of items shown to the available space. A SectionList is composed by one or more SectionListItem which can contain any XAML code. Each SectionListItem may have a Header and a ViewAll button to navigate to the list of items shown. The control shows a progress indicator while loading. If an exception occurs during the load, an error message is shown.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/SectionList

###SplitterCard Control
The SplitterCard control applies a specific design to strings. For any given string, the controls split the text by spaces. The first two words in the text are displayed one over the other using a specific style and highlighting the first one.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/SplitterCard

##Foundation Controls
###HtmlBlock
The HtmlBlock renders Html formatted content using a native Xaml representation. The control is optimized to friendly visualize Html content within your Apps creating a Xaml reading view for your content. It applies a set of default styles to represent each Html tag, the default styles can be overriden as your preference. It supports most common Html tags as well as videos from YouTube and Channel9 embedded using an iframe tag. Following are the currently supported Html tags: a, article, blockQuote, cite, code, dd, details, div, dl, dt, em, figCaption, figure, footer, h1, h2, h3, h4, h5, h6, header, i, img, label, li, main, mark, ol, p, pre, q, section, span, strong, summary, table, td, th, time, tr, ul. Finally, the control does not interpret or parse JavaScript code as is not thought download content from Internet (use the WebView control instead).

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/HtmlBlock

###VisualBreakpoints
Enables the definition of different visual breakpoints for a certain layout as well as modifies the properties of child controls based on the breakpoints defined. In other words, adds the ability to change the layout and property values of controls based on the defined 'breakpoint values'. There are two main advantages over the platform VisualStateManager control: 1) all the visual breakpoints are defined in a centralized JSON file, which can reference other JSON files; 2) allows the modification of properties inside controls that belongs to DataTemplates.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/VisualBreakpoints

###ImageEx Control
The ImageEx control extends the default Image platform control improving the performance and responsiveness of your Apps. Source images are downloaded asynchronously showing a load indicator while in progress. Once downloaded, the source image is stored in the App local cache to preserve resources and load time next time the image needs to be displayed.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/ImageEx

###GifControl Control
The GifControl allows animated gif renderization in XAML. [ImageEx Control](#image-ex) determines the format of the inbound image and uses Gif Control in case the image is an animated gif.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/GifControl

###VirtualBox Control
The VirtualBox control allows to redimension any XAML DataTemplate proportionaly. The control works directly with the underlying ContentPresenter to have a smooth behavior and high optimized performance.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/Virtualbox

###RelativeBox Control
The RelativeBox control uses XAML to apply a responsive behavior to the DataTemplate configured.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/Relativebox

###Relative and VirtualBox
The RelativeBox control can be used together with the VirtualBox control to apply a better responsive behavior to the DataTemplate configured.

###SearchBox Control
The SearchBox control allows to handle the App search feature. You can decide how the control will be displayed using properties Foreground, Background, PlaceHolderText, FontSize, etc. The SearchCommand property establish the command to execute when the user press enter or click the magnifier.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/SearchBox

###InfiniteScroll Control
To create the Infinite Scroll behavior we use the EndOfScrollCommand attached property. Applying the EndOfScrollCommand to a Xaml control (ListView, GridView or ScrollViewer) we look for changes in the VerticalOffset property. When the VerticalOffset reaches the end of the scrollable size it executes a command in C#. In the sample, the command execution results in loading more items and add them at the end of the item collection.

*View code*
https://github.com/wasteam/waslibs/blob/master/src/AppStudio.Uwp/Commands/EndOfScrollCommand.cs

##App Services
###Navigation Service
The NavigationService service handles the complexity of navigating among App pages. It can be used in the main rootFrame as well as in other internal frames, like a ShellControl with Hamburger button.

The navigation can be implemented in multiple ways: using the .NET Type of the page we want to navigate to; using a string with the page name as target page; or through an element which implements the INavigable interface. We can use the NavigationService to open the web browser as well.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Navigation

###AppCache Service
The AppCache is a service class which use local storage to maintain persisten information among App executions hiding the complexity of saving to and load from the local storage the elements added to memory.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Cache

##Utilities
###ErrorNotification Control
The ErrorNotificationControl allows to show a message when an exception occurs. You can configure the message background color and the user can close it once read.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Controls/ErrorNotificationControl

###ActionsCommandBar Control
The ActionsCommandBar control extends the system Windows.UI.Xaml.Controls.CommandBar allowing to dynamically load the AppBarButtons through binding the control to a List of ActionInfo items created from C#. The control can define the AppBarButtons in XAML as well.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Actions

###Animation Extensions
The Animation Extensions are a set of extension Methods on the FrameworkElement control which allows to execute animations from C# code. The animations can be invoked asynchronously.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Extensions

###Converters
Converters allow you to transform a certain value from a data type in other different value. Using Converters leads to have a cleaner XAML code. In the samples shown, the first converter is used to change the Visibility of an image based in the value a Toggle control. If the Toggle is True (Boolean value), the converter returns 'Visible' for the Visibility property of the image control. When the Toggle is False, it returns 'Collapsed' for the Visibility property.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Converters

##Labs
This section contains the information for those controls developed but still not being used in the Apps generated by Windows App Studio.
###ResponsiveGridView Contro
Improved experience and performance for the exsisting ResponsiveGridView control.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Labs/ResponsiveGridView

###Accordion Control
The Accordion Control display a set of images stacked vertically, showing the selected image using the full size. The "stacked" images below the selected one are pre-visualized in the stack waiting to be slided vertically. By default, four images are shown in the stack. If the collection have more than four images, the remain ones will appear as the user slide the existing ones.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Labs/Accordion

###SlideShow Control
The SlideShow Control creates animated transitions between a set of images. You can control the transitions using the DelayInterval and FadeIntervale properties. The Delay Interval define how many time an image remain displayed before start the transition to the next one; The FadeInterval defines the duration of the face-in efect to display the next image.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Labs/SlideShow

###ShapeImage Control
Allows to show an image using a specific shape to display it. Currently it supports tree kind of pre-defined shapes: Border, Elipse and Rectangle.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Labs/ShapeImage

###AutoHide Control
This is generic control which allows you to hide / show a certain UI control with fade-out / fade-in effect. It is based on the existing user interaction done by mouse movement. If the user does not move the mouse for a certain duration the control contained will be hidden. If mouse move is detected, the control contained will appear.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Labs/AutoHide

###Mosaic Control
This responsive control allows to create a random mosaic of images making size variations. The control uses an specific with to create the mosaic.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.Uwp/Labs/Mosaic

#Data Providers Library
This library contains the implementation of all the data sources available in
Windows App Studio apps.

This is a Portable Class Library that can be used in:
- Windows 10
- Windows 8.1
- Windows Phone 8.1

Among the Data Provider classes implemented in Windows App Studio, those which access third party data, help handling the complexity of each particular provider (API calls, authentication and authorization requirements, data parsing, etc.) so provides a smooth and uniform way to access the content from these providers.  All Data Providers take advantage of the AppCache service to improve the App performance.

##Facebook Data Provider
The FacebookDataProvider allow to retrieve Facebook data through its API. You have to be registered in Facebook Apps to be able to interact with the Facebook API and you must obtain an AppId and AppSecret to configure the data access. Finally, you must use the Page ID from what you want to get the information.

*Further info*
https://developers.facebook.com/apps/
https://developers.facebook.com/docs/graph-api/using-graph-api

*View Code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.DataProviders/Facebook

##Twitter Data Provider
The TwitterDataProvider retrieve data using the Twitter API. To be able to request Twitter data, the user must be registered in Twitter Apps and obtain a ConsumerSecret, an AccessToken and an AccessTokenSecret. This Data Provider can retrieve the user TimeLine or gather data by Twitter User Name or Hashtag.
*Further info*
https://apps.twitter.com/
https://dev.twitter.com/rest/public

*View Code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.DataProviders/Twitter

##Flickr Data Provider
The FlickrDataProvider gets images using the Flickr API. You can retrieve content based on tags or you can access the images from a Flickr account by using the UserID. To resolve which UserID is assigned to a certain Flickr account use http://idgettr.com/

*Further info*
https://www.flickr.com/services/feeds/
http://idgettr.com/

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.DataProviders/Flickr

##YouTube Data Provider
The YouTube Data Provider retrieve data through the YouTube API by using the YouTube ChannelID, the PlaylistID, or a search term. To be able to request data using this provider, you must be registered for Google Developers Console and get an API Key.

*Further info*
https://console.developers.google.com/project
https://dev.twitter.com/rest/public

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.DataProviders/YouTube

##WordPress Data Provider
The WordPress Data Provider retrieve data from the Word Press blog configured in the property WordPressQuery. You can configure the search in the Data Provider by using one of the following options: Posts, Categories or Tags. The information is read in JSON format and transformed to the WordPressSchema entity. This Data Provider relies on the REST API to access the source content. If the target blog is self-hosted (not in Wordpress.com) it must have the JetPack plug-in installed and the JSON API enabled.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.DataProviders/WordPress

##Rss Data Provider
The RssDataProvider retrieve information from the configured RSS Url, the data is read form the source in XML format and transformed to a RssSchema entity.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.DataProviders/Rss

##Bing Data Provider
The Bing DataProvider allows you to retreive Microsoft Bing web search engine results direct to your App.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.DataProviders/Bing

##LocalStorage Data Provider
This Data Provider access data from the LocalStorage. You can configure which file will be used as content source. The information, stored in JSON format, is transformed to the specified data type.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.DataProviders/LocalStorage

##REST API Data Provider
Among the Data Provider classes implemented in Windows App Studio, those which access third party data, help handling the complexity of each particular provider (API calls, authentication and authorization requirements, data parsing, etc.) so provides a smooth and uniform way to access the content from these providers.  All Data Providers take advantage of the AppCache service to improve the App performance.

The RestApiDataProvider retrieve information from the configured endpoint Url. You can configure de pagination type and items per page.

*View code*
https://github.com/wasteam/waslibs/tree/master/src/AppStudio.DataProviders/RestApi

# Common
This library contains utility classes to create XAML applications.
This is a Portable Class Library that can be used in:
- Windows 10
- Windows 8.1
- Windows Phone 8.1


text:
describe("App.Models.Note", function () {
  it("has default values", function () {
    // Create empty note model.
    var model = new App.Models.Note();

    expect(model).to.be.ok;
    expect(model.get("title")).to.equal("");
    expect(model.get("text")).to.equal("*Edit your note!*");
    expect(model.get("createdAt")).to.be.a("Date");
  });

  it("sets passed attributes", function () {
    var model = new App.Models.Note({
      title: "Grocery List",
      text: "* Milk\n* Eggs\n*Coffee"
    });

    expect(model.get("title")).to.equal("Grocery List");
    expect(model.get("text")).to.equal("* Milk\n* Eggs\n*Coffee");
  });
});


text:
<!DOCTYPE html>

    <meta http-equiv="refresh" content="0;URL=../../libc/fn.isprint.html">

Redirecting to ../../libc/fn.isprint.html...


text:
#pragma once

#include <algorithm>  // std::fill, std::generate
#include <cmath>      // sqrt
#include <numeric>    // std::accumulate

#include "tiny_dnn/core/framework/tensor.h"

namespace tiny_dnn {

template <typename T>
void print_pack(std::ostream &out, T t) {  // TODO: C++17 allows easier printing
  out << t;
}

template <typename T, typename U, typename... Args>
void print_pack(std::ostream &out, T t, U u, Args... args) {
  out << t << ',';
  print_pack(out, u, args...);
}

template <typename T, size_t kDim, typename... Args>
inline std::ostream &print_last_two_dimesions(std::ostream &os,
                                              const Tensor<T, kDim> &tensor,
                                              const Args... args) {
  const std::array<size_t, kDim> &shape = tensor.shape();
  for (size_t k = 0; k < shape[kDim - 2]; ++k) {
    for (size_t l = 0; l < shape[kDim - 1]; ++l) {
      os << "\t" << tensor.host_at(args..., k, l);
    }
    os << "\n";
  }
  return os;
}

template <typename T,
          size_t kDim,
          typename... Args,
          typename std::enable_if<sizeof...(Args) == kDim - 3, int>::type = 0>
inline std::ostream &print_last_n_dimesions(std::ostream &os,
                                            const Tensor<T, kDim> &tensor,
                                            const int d,
                                            const Args... args) {
  // const std::array<size_t, kDim>& shape = tensor.shape();
  // const size_t n_dim = sizeof...(args);
  os << "Tensor(";
  print_pack(os, d, args...);
  os << ",:,:):\n";
  print_last_two_dimesions(os, tensor, d, args...);
  return os;
}

template <typename T,
          size_t kDim,
          typename... Args,
          typename std::enable_if<(sizeof...(Args) < kDim - 3), int>::type = 0>
inline std::ostream &print_last_n_dimesions(std::ostream &os,
                                            const Tensor<T, kDim> &tensor,
                                            const int d,
                                            const Args... args) {
  const std::array<size_t, kDim> &shape = tensor.shape();
  const size_t n_dim = sizeof...(args);
  for (size_t k = 0; k < shape[n_dim + 1]; ++k) {
    print_last_n_dimesions(os, tensor, d, args..., k);
  }
  return os;
}

// TODO(Ranld): static_if (C++17)
template <typename T>
inline std::ostream &operator<<(std::ostream &os, const Tensor<T, 1> &tensor) {
  const std::array<size_t, 1> &shape = tensor.shape();
  for (size_t i = 0; i < shape[0]; ++i) os << "\t" << tensor.host_at(i);
  os << "\n";
  return os;
}

template <typename T>
inline std::ostream &operator<<(std::ostream &os, const Tensor<T, 2> &tensor) {
  print_last_two_dimesions(os, tensor);
  return os;
}

/**
 * Overloaded method to print the Tensor class to the standard output
 * @param os
 * @param tensor
 * @return
 */
template <typename T, size_t kDim>
inline std::ostream &operator<<(std::ostream &os,
                                const Tensor<T, kDim> &tensor) {
  const std::array<size_t, kDim> &shape = tensor.shape();
  for (size_t i = 0; i < shape[0]; ++i) print_last_n_dimesions(os, tensor, i);
  return os;
}

// utilities for element-wise and tensor-scalar/scalar-tensor operations

template <typename TD, typename TS1, typename TS2, typename F, size_t kDim>
void binary_tensor_tensor_elementwise_operation(Tensor<TD, kDim> &dst,
                                                const Tensor<TS1, kDim> &src1,
                                                const Tensor<TS2, kDim> &src2,
                                                F f) {
  if (src1.shape() != src2.shape()) {
    throw nn_error("Tensor must have same shape");
  }

  dst.resize(src1.shape());

  auto pdst  = dst.host_begin();
  auto psrc1 = src1.host_begin();
  auto psrc2 = src2.host_begin();

  for_i(true, dst.size(), [pdst, psrc1, psrc2, &f](size_t i) {
    pdst[i] = f(psrc1[i], psrc2[i]);
  });
}

template <typename TD, typename TS, typename F, size_t kDim>
void unary_tensor_elementwise_operation(Tensor<TD, kDim> &dst,
                                        const Tensor<TS, kDim> &src,
                                        F f) {
  dst.resize(src.shape());

  auto pdst = dst.host_begin();
  auto psrc = src.host_begin();

  for_i(true, dst.size(), [pdst, psrc, &f](size_t i) { pdst[i] = f(psrc[i]); });
}

template <typename TD, typename TS1, typename TS2, typename F, size_t kDim>
void binary_tensor_scalar_operation(Tensor<TD, kDim> &dst,
                                    const Tensor<TS1, kDim> &src1,
                                    TS2 src2,
                                    F f) {
  dst.resize(src1.shape());

  auto pdst  = dst.host_begin();
  auto psrc1 = src1.host_begin();

  for_i(true, dst.size(),
        [pdst, psrc1, src2, &f](size_t i) { pdst[i] = f(psrc1[i], src2); });
}

template <typename TD, typename TS1, typename TS2, typename F, size_t kDim>
void binary_scalar_tensor_operation(Tensor<TD, kDim> &dst,
                                    TS1 src1,
                                    const Tensor<TS2, kDim> &src2,
                                    F f) {
  dst.resize(src2.shape());

  auto pdst  = dst.host_begin();
  auto psrc2 = src2.host_begin();

  for_i(true, dst.size(),
        [pdst, src1, psrc2, &f](size_t i) { pdst[i] = f(src1, psrc2[i]); });
}

// implementation of

namespace details {

template <typename TS1, typename TS2>
auto plus(TS1 s1, TS2 s2) -> decltype(s1 + s2) {
  return s1 + s2;
}

template <typename TS1, typename TS2>
auto minus(TS1 s1, TS2 s2) -> decltype(s1 - s2) {
  return s1 - s2;
}

template <typename TS1, typename TS2>
auto multiplies(TS1 s1, TS2 s2) -> decltype(s1 * s2) {
  return s1 * s2;
}

template <typename TS1, typename TS2>
auto divides_checked(TS1 s1, TS2 s2) -> decltype(s1 / s2) {
  typedef decltype(s1 / s2) result_type;
  return (s2 == result_type{}) ? std::numeric_limits<result_type>::quiet_NaN()
                               : s1 / s2;
}

template <typename TS1, typename TS2>
auto divides_unchecked(TS1 s1, TS2 s2) -> decltype(s1 / s2) {
  return s1 / s2;
}

template <typename T>
T sqrt_checked(T s1) {
  return (s1 <= T{}) ? std::numeric_limits<T>::quiet_NaN() : sqrt(s1);
}

// do not inline - this function converts the std::exp
// overloadeds in a single templated function.
template <typename T>
T exp(T s1) {
  return std::exp(s1);
}

}  // namespace details

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_add(Tensor<TD, kDim> &dst, TS1 src1, const Tensor<TS2, kDim> &src2) {
  binary_scalar_tensor_operation(dst, src1, src2, details::plus<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_add(Tensor<TD, kDim> &dst, const Tensor<TS1, kDim> &src1, TS2 src2) {
  binary_tensor_scalar_operation(dst, src1, src2, details::plus<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_add(Tensor<TD, kDim> &dst,
               const Tensor<TS1, kDim> &src1,
               const Tensor<TS2, kDim> &src2) {
  binary_tensor_tensor_elementwise_operation(dst, src1, src2,
                                             details::plus<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_sub(Tensor<TD, kDim> &dst, TS1 src1, const Tensor<TS2, kDim> &src2) {
  binary_scalar_tensor_operation(dst, src1, src2, details::minus<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_sub(Tensor<TD, kDim> &dst, const Tensor<TS1, kDim> &src1, TS2 src2) {
  binary_tensor_scalar_operation(dst, src1, src2, details::minus<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_sub(Tensor<TD, kDim> &dst,
               const Tensor<TS1, kDim> &src1,
               const Tensor<TS2, kDim> &src2) {
  binary_tensor_tensor_elementwise_operation(dst, src1, src2,
                                             details::minus<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_mul(Tensor<TD, kDim> &dst, TS1 src1, const Tensor<TS2, kDim> &src2) {
  binary_scalar_tensor_operation(dst, src1, src2,
                                 details::multiplies<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_mul(Tensor<TD, kDim> &dst, const Tensor<TS1, kDim> &src1, TS2 src2) {
  binary_tensor_scalar_operation(dst, src1, src2,
                                 details::multiplies<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_mul(Tensor<TD, kDim> &dst,
               const Tensor<TS1, kDim> &src1,
               const Tensor<TS2, kDim> &src2) {
  binary_tensor_tensor_elementwise_operation(dst, src1, src2,
                                             details::multiplies<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_div(Tensor<TD, kDim> &dst, TS1 src1, const Tensor<TS2, kDim> &src2) {
  binary_scalar_tensor_operation(dst, src1, src2,
                                 details::divides_checked<TS1, TS2>);
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_div(Tensor<TD, kDim> &dst, const Tensor<TS1, kDim> &src1, TS2 src2) {
  if (src2 == TS2(0.0)) {
    dst.resize(src1.shape());
    dst.fill(std::numeric_limits<TD>::quiet_NaN());
  } else {
    binary_tensor_scalar_operation(dst, src1, src2,
                                   details::divides_unchecked<TS1, TS2>);
  }
}

template <typename TD, typename TS1, typename TS2, size_t kDim>
void layer_div(Tensor<TD, kDim> &dst,
               const Tensor<TS1, kDim> &src1,
               const Tensor<TS2, kDim> &src2) {
  binary_tensor_tensor_elementwise_operation(
    dst, src1, src2, details::divides_checked<TS1, TS2>);
}

template <typename TD, typename TS, size_t kDim>
void layer_sqrt(Tensor<TD, kDim> &dst, const Tensor<TS, kDim> &src1) {
  return unary_tensor_elementwise_operation(dst, src1,
                                            details::sqrt_checked<TS>);
}

template <typename TD, typename TS, size_t kDim>
void layer_exp(Tensor<TD, kDim> &dst, const Tensor<TS, kDim> &src1) {
  return unary_tensor_elementwise_operation(dst, src1, details::exp<TS>);
}

}  // namespace tiny_dnn