<commit_before>/**
 * @author Markus Näsman
 * @copyright 2012 (c) Markus Näsman <markus at botten dot org >
 * @license Copyright (c) 2012, Markus Näsman
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL MARKUS NÄSMAN BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * IMPORTS
 */
var assert = require('assert');
var color_diff = require('../lib/diff');

/**
 * TESTS
 */

/**
 * CIEDE2000 tests the diff.cie2000.
 * Cases taken from the paper "The CIEDE2000 Color-Difference Formula:
 * Implementation Notes, Supplementary Test Data, and Mathematical Observations"
 * by Gaurav Sharma, Wencheng Wu and Edul N. Dalal.
 */
describe('diff', function(){
  describe('#ciede2000()', function(){
    it('should return expected difference #1', function(){
      assert.equal(2.0425, round(color_diff.ciede2000({'L' : 50.0000,
                                                       'a' : 2.6772,
                                                       'b' : -79.7751
                                                      },
                                                      {'L' : 50.0000,
                                                       'a' : 0.0000,
                                                       'b' : -82.7485
                                                      })));
    });
    it('should return expected difference #2', function(){
      assert.equal(2.8615, round(color_diff.ciede2000({'L' : 50.0000,
                                                       'a' : 3.1571,
                                                       'b' : -77.2803
                                                      },
                                                      {'L' : 50.0000,
                                                       'a' : 0.0000,
                                                       'b' : -82.7485
                                                      })));
    });
    it('should return expected difference #3', function(){
      assert.equal(0.9082, round(color_diff.ciede2000({'L' : 2.0776,
                                                       'a' : 0.0795,
                                                       'b' : -1.1350
                                                      },
                                                      {'L' : 0.9033,
                                                       'a' : -0.0636,
                                                       'b' : -0.5514
                                                      })));
    });
    it('should throw error', function(){
      assert.throws(
        function(){ color_diff.ciede2000({'L':NaN, 'a':NaN, 'b':NaN},
                                         {'L':0,'a':0,'b':0})
                  },
        Error)
    });
  })
});

/**
 * INTERNAL FUNCTIONS
 */

function round(n){ return Math.round(n*10000)/10000; }

// Local Variables:
// allout-layout: t
// js-indent-level: 2
// End:
<commit_msg>Improved testing of CIEDE2000<commit_after>/**
 * @author Markus Näsman
 * @copyright 2012 (c) Markus Näsman <markus at botten dot org >
 * @license Copyright (c) 2012, Markus Näsman
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of the <organization> nor the
 *      names of its contributors may be used to endorse or promote products
 *      derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL MARKUS NÄSMAN BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * IMPORTS
 */
var assert = require('assert');
var color_diff = require('../lib/diff');

/**
 * TESTS
 */

/**
 * CIEDE2000 tests the diff.cie2000.
 * Cases taken from the paper "The CIEDE2000 Color-Difference Formula:
 * Implementation Notes, Supplementary Test Data, and Mathematical Observations"
 * by Gaurav Sharma, Wencheng Wu and Edul N. Dalal.
 */
describe('diff', function(){
  describe('#ciede2000()', function(){
    it("should use the true chroma difference (#1)", function(){
      assert_ciede2000_diff(2.0425,
                            {"L" : 50.0000,
                             "a" : 2.6772,
                             "b" : -79.7751
                            },
                            {"L" : 50.0000,
                             "a" : 0.0000,
                             "b" : -82.7485
                            });
    });
    it("should use the true chroma difference (#2)", function(){
      assert_ciede2000_diff(2.8615,
                            {"L" : 50.0000,
                             "a" : 3.1571,
                             "b" : -77.2803
                            },
                            {"L" : 50.0000,
                             "a" : 0.0000,
                             "b" : -82.7485
                            });
    });
    it("should use the true chroma difference (#3)", function(){
      assert_ciede2000_diff(3.4412,
                            {"L" : 50.0000,
                             "a" : 2.8361,
                             "b" : -74.0200
                            },
                            {"L" : 50.0000,
                             "a" : 0.0000,
                             "b" : -82.7485
                            });
    });
    it("should use the true hue difference (#4)", function(){
      assert_ciede2000_diff(1.0000,
                            {"L" : 50.0000,
                             "a" : -1.3802,
                             "b" : -84.2814
                            },
                            {"L" : 50.0000,
                             "a" : 0.0000,
                             "b" : -82.7485
                            });
    });
    it("should use the true hue difference (#5)", function(){
      assert_ciede2000_diff(1.0000,
                            {"L" : 50.0000,
                             "a" : -1.1848,
                             "b" : -84.8006
                            },
                            {"L" : 50.0000,
                             "a" : 0.0000,
                             "b" : -82.7485
                            });
    });
    it("should use the true hue difference (#6)", function(){
      assert_ciede2000_diff(1.0000,
                            {"L" : 50.0000,
                             "a" : -0.9009,
                             "b" : -85.5211
                            },
                            {"L" : 50.0000,
                             "a" : 0.0000,
                             "b" : -82.7485
                            });
    });
    it("should use the correct arctangent computation (#7)", function(){
      assert_ciede2000_diff(2.3669,
                            {"L" : 50.0000,
                             "a" : 0.0000,
                             "b" : 0.0000
                            },
                            {"L" : 50.0000,
                             "a" : -1.0000,
                             "b" : 2.0000
                            });
    });
    it("should use the correct arctangent computation (#8)", function(){
      assert_ciede2000_diff(2.3669,
                            {"L" : 50.0000,
                             "a" : -1.0000,
                             "b" : 2.0000
                            },
                            {"L" : 50.0000,
                             "a" : 0.0000,
                             "b" : 0.0000
                            });
    });
    it("should use the correct arctangent computation (#9)", function(){
      assert_ciede2000_diff(7.1792,
                            {"L" : 50.0000,
                             "a" : 2.4900,
                             "b" : -0.0010
                            },
                            {"L" : 50.0000,
                             "a" : -2.4900,
                             "b" : 0.0009
                            });
    });
    it("should use the correct arctangent computation (#10)", function(){
      assert_ciede2000_diff(7.1792,
                            {"L" : 50.0000,
                             "a" : 2.4900,
                             "b" : -0.0010
                            },
                            {"L" : 50.0000,
                             "a" : -2.4900,
                             "b" : 0.0010
                            });
    });
    it("should use the correct arctangent computation (#11)", function(){
      assert_ciede2000_diff(7.2195,
                            {"L" : 50.0000,
                             "a" : 2.4900,
                             "b" : -0.0010
                            },
                            {"L" : 50.0000,
                             "a" : -2.4900,
                             "b" : 0.0011
                            });
    });
    it("should use the correct arctangent computation (#12)", function(){
      assert_ciede2000_diff(7.2195,
                            {"L" : 50.0000,
                             "a" : 2.4900,
                             "b" : -0.0010
                            },
                            {"L" : 50.0000,
                             "a" : -2.4900,
                             "b" : 0.0012
                            });
    });
    it("should use the correct arctangent computation (#13)", function(){
      assert_ciede2000_diff(4.8045,
                            {"L" : 50.0000,
                             "a" : -0.0010,
                             "b" : 2.4900
                            },
                            {"L" : 50.0000,
                             "a" : 0.0009,
                             "b" : -2.4900
                            });
    });
    it("should use the correct arctangent computation (#14)", function(){
      assert_ciede2000_diff(4.8045,
                            {"L" : 50.0000,
                             "a" : -0.0010,
                             "b" : 2.4900
                            },
                            {"L" : 50.0000,
                             "a" : 0.0010,
                             "b" : -2.4900
                            });
    });
    it("should use the correct arctangent computation (#15)", function(){
      assert_ciede2000_diff(4.7461,
                            {"L" : 50.0000,
                             "a" : -0.0010,
                             "b" : 2.4900
                            },
                            {"L" : 50.0000,
                             "a" : 0.0011,
                             "b" : -2.4900
                            });
    });
    it("should use the correct arctangent computation (#16)", function(){
      assert_ciede2000_diff(4.3065,
                            {"L" : 50.0000,
                             "a" : 2.5000,
                             "b" : 0.0000
                            },
                            {"L" : 50.0000,
                             "a" : 0.0000,
                             "b" : -2.5000
                            });
    });
    it("should work for large color differences (#17)", function(){
      assert_ciede2000_diff(27.1492,
                            {"L" : 50.0000,
                             "a" : 2.5000,
                             "b" : 0.0000
                            },
                            {"L" : 73.0000,
                             "a" : 25.0000,
                             "b" : -18.0000
                            });
    });
    it("should work for large color differences (#18)", function(){
      assert_ciede2000_diff(22.8977,
                            {"L" : 50.0000,
                             "a" : 2.5000,
                             "b" : 0.0000
                            },
                            {"L" : 61.0000,
                             "a" : -5.0000,
                             "b" : 29.0000
                            });
    });
    it("should work for large color differences (#19)", function(){
      assert_ciede2000_diff(31.9030,
                            {"L" : 50.0000,
                             "a" : 2.5000,
                             "b" : 0.0000
                            },
                            {"L" : 56.0000,
                             "a" : -27.0000,
                             "b" : -3.0000
                            });
    });
    it("should work for large color differences (#20)", function(){
      assert_ciede2000_diff(19.4535,
                            {"L" : 50.0000,
                             "a" : 2.5000,
                             "b" : 0.0000
                            },
                            {"L" : 58.0000,
                             "a" : 24.0000,
                             "b" : 15.0000
                            });
    });
    it("should produce numbers found in the CIE technical report (#21)", function(){
      assert_ciede2000_diff(1.0000,
                            {"L" : 50.0000,
                             "a" : 2.5000,
                             "b" : 0.0000
                            },
                            {"L" : 50.0000,
                             "a" : 3.1736,
                             "b" : 0.5854
                            });
    });
    it("should produce numbers found in the CIE technical report (#22)", function(){
      assert_ciede2000_diff(1.0000,
                            {"L" : 50.0000,
                             "a" : 2.5000,
                             "b" : 0.0000
                            },
                            {"L" : 50.0000,
                             "a" : 3.2972,
                             "b" : 0.0000
                            });
    });
    it("should produce numbers found in the CIE technical report (#23)", function(){
      assert_ciede2000_diff(1.0000,
                            {"L" : 50.0000,
                             "a" : 2.5000,
                             "b" : 0.0000
                            },
                            {"L" : 50.0000,
                             "a" : 1.8634,
                             "b" : 0.5757
                            });
    });
    it("should produce numbers found in the CIE technical report (#24)", function(){
      assert_ciede2000_diff(1.0000,
                            {"L" : 50.0000,
                             "a" : 2.5000,
                             "b" : 0.0000
                            },
                            {"L" : 50.0000,
                             "a" : 3.2592,
                             "b" : 0.3350
                            });
    });
    it("should produce numbers found in the CIE technical report (#25)", function(){
      assert_ciede2000_diff(1.2644,
                            {"L" : 60.2574,
                             "a" : -34.0099,
                             "b" : 36.2677
                            },
                            {"L" : 60.4626,
                             "a" : -34.1751,
                             "b" : 39.4387
                            });
    });
    it("should produce numbers found in the CIE technical report (#26)", function(){
      assert_ciede2000_diff(1.2630,
                            {"L" : 63.0109,
                             "a" : -31.0961,
                             "b" : -5.8663
                            },
                            {"L" : 62.8187,
                             "a" : -29.7946,
                             "b" : -4.0864
                            });
    });
    it("should produce numbers found in the CIE technical report (#27)", function(){
      assert_ciede2000_diff(1.8731,
                            {"L" : 61.2901,
                             "a" : 3.7196,
                             "b" : -5.3901
                            },
                            {"L" : 61.4292,
                             "a" : 2.2480,
                             "b" : -4.9620
                            });
    });
    it("should produce numbers found in the CIE technical report (#28)", function(){
      assert_ciede2000_diff(1.8645,
                            {"L" : 35.0831,
                             "a" : -44.1164,
                             "b" : 3.7933
                            },
                            {"L" : 35.0232,
                             "a" : -40.0716,
                             "b" : 1.5901
                            });
    });
    it("should produce numbers found in the CIE technical report (#29)", function(){
      assert_ciede2000_diff(2.0373,
                            {"L" : 22.7233,
                             "a" : 20.0904,
                             "b" : -46.6940
                            },
                            {"L" : 23.0331,
                             "a" : 14.9730,
                             "b" : -42.5619
                            });
    });
    it("should produce numbers found in the CIE technical report (#30)", function(){
      assert_ciede2000_diff(1.4146,
                            {"L" : 36.4612,
                             "a" : 47.8580,
                             "b" : 18.3852
                            },
                            {"L" : 36.2715,
                             "a" : 50.5065,
                             "b" : 21.2231
                            });
    });
    it("should produce numbers found in the CIE technical report (#31)", function(){
      assert_ciede2000_diff(1.4441,
                            {"L" : 90.8027,
                             "a" : -2.0831,
                             "b" : 1.4410
                            },
                            {"L" : 91.1528,
                             "a" : -1.6435,
                             "b" : 0.0447
                            });
    });
    it("should produce numbers found in the CIE technical report (#32)", function(){
      assert_ciede2000_diff(1.5381,
                            {"L" : 90.9257,
                             "a" : -0.5406,
                             "b" : -0.9208
                            },
                            {"L" : 88.6381,
                             "a" : -0.8985,
                             "b" : -0.7239
                            });
    });
    it("should produce numbers found in the CIE technical report (#33)", function(){
      assert_ciede2000_diff(0.6377,
                            {"L" : 6.7747,
                             "a" : -0.2908,
                             "b" : -2.4247
                            },
                            {"L" : 5.8714,
                             "a" : -0.0985,
                             "b" : -2.2286
                            });
    });
    it("should produce numbers found in the CIE technical report (#34)", function(){
      assert_ciede2000_diff(0.9082,
                            {"L" : 2.0776,
                             "a" : 0.0795,
                             "b" : -1.1350
                            },
                            {"L" : 0.9033,
                             "a" : -0.0636,
                             "b" : -0.5514
                            });
    });
    it("should throw error", function(){
      assert.throws(
        function(){ color_diff.ciede2000({"L" : NaN,
                                          "a" : NaN,
                                          "b" : NaN},
                                         {"L" : 0,
                                          "a" : 0,
                                          "b" : 0
                                         })
                  },
        Error)
    });
  })
});

/**
 * INTERNAL FUNCTIONS
 */

function assert_ciede2000_diff(expected, c1, c2){
  assert.equal(expected, round(color_diff.ciede2000(c1, c2)));
  assert.equal(expected, round(color_diff.ciede2000(c2, c1)));
}

function round(n){ return Math.round(n*10000)/10000; }

// Local Variables:
// allout-layout: t
// js-indent-level: 2
// End:
<|endoftext|>


<commit_before>var createContext = require('./util/create-context')
var createREGL = require('../../regl')
var tape = require('tape')

tape('drawing', function (t) {
  var gl = createContext(5, 5)
  var regl = createREGL(gl)

  function checkPixmap (args, expected, remark) {
    var base = {
      frag: [
        'precision mediump float;',
        'void main() {',
        'gl_FragColor = vec4(1, 1, 1, 1);',
        '}'
      ].join('\n'),

      vert: [
        'precision mediump float;',
        'attribute vec2 position;',
        'varying vec4 fragColor;',
        'void main() {',
        'gl_Position=vec4((position - 2.0) / 2.1, 0, 1);',
        '}'
      ].join('\n'),

      attributes: {
        position: regl.buffer([0, 0, 4, 0, 4, 4, 0, 4])
      },

      depth: {enable: false, mask: false}
    }

    Object.keys(args).forEach(function (x) {
      base[x] = args[x]
    })

    function runCheck (suffix) {
      var pixels = regl.read()
      var actual = new Array(25)
      for (var i = 0; i < 25; ++i) {
        actual[i] = Math.min(1, pixels[4 * i])
      }
      t.same(actual, expected, remark + ' - ' + suffix)
    }

    var command = regl(base)

    regl.clear({color: [0, 0, 0, 0]})
    command()
    runCheck('static')

    regl.clear({color: [0, 0, 0, 0]})
    command(1)
    runCheck('batch')

    regl.clear({color: [0, 0, 0, 0]})
    command(function () {
      regl.draw()
    })
    runCheck('scope')
  }

  // points
  checkPixmap({
    primitive: 'points',
    count: 4
  }, [
    1, 0, 0, 0, 1,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    1, 0, 0, 0, 1
  ], 'point')

  // lines
  checkPixmap({
    primitive: 'lines',
    count: 2
  }, [
    1, 1, 1, 1, 1,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0
  ], 'line')

  // line strip
  checkPixmap({
    primitive: 'line strip',
    count: 3
  }, [
    1, 1, 1, 1, 1,
    0, 0, 0, 0, 1,
    0, 0, 0, 0, 1,
    0, 0, 0, 0, 1,
    0, 0, 0, 0, 1
  ], 'line strip')

  // line loop
  checkPixmap({
    primitive: 'line loop',
    count: 4
  }, [
    1, 1, 1, 1, 1,
    1, 0, 0, 0, 1,
    1, 0, 0, 0, 1,
    1, 0, 0, 0, 1,
    1, 1, 1, 1, 1
  ], 'line loop')

  // triangles
  checkPixmap({
    primitive: 'triangles',
    count: 3
  }, [
    1, 1, 1, 1, 1,
    0, 1, 1, 1, 1,
    0, 0, 1, 1, 1,
    0, 0, 0, 1, 1,
    0, 0, 0, 0, 1
  ], 'triangles')

  // triangle strip
  checkPixmap({
    primitive: 'triangle strip',
    count: 4
  }, [
    1, 1, 1, 1, 1,
    0, 1, 1, 1, 1,
    0, 0, 1, 1, 1,
    0, 1, 1, 1, 1,
    1, 1, 1, 1, 1
  ], 'triangle strip')

  // triangle fan
  checkPixmap({
    primitive: 'triangle fan',
    count: 4
  }, [
    1, 1, 1, 1, 1,
    1, 1, 1, 1, 1,
    1, 1, 1, 1, 1,
    1, 1, 1, 1, 1,
    1, 1, 1, 1, 1
  ], 'triangle fan')

  regl.destroy()
  createContext.destroy(gl)
  t.end()
})
<commit_msg>switch buffer size in draw to 8x8<commit_after>var createContext = require('./util/create-context')
var createREGL = require('../../regl')
var tape = require('tape')

tape('drawing', function (t) {
  var gl = createContext(8, 8)
  var regl = createREGL(gl)

  function checkPixmap (args, expected, remark) {
    var base = {
      frag: [
        'precision mediump float;',
        'void main() {',
        'gl_FragColor = vec4(1, 1, 1, 1);',
        '}'
      ].join('\n'),

      vert: [
        'precision mediump float;',
        'attribute vec2 position;',
        'varying vec4 fragColor;',
        'void main() {',
        'gl_Position=vec4(0.25 * (position - 3.5), 0, 1);',
        '}'
      ].join('\n'),

      attributes: {
        position: regl.buffer([0, 0, 4, 0, 4, 4, 0, 4])
      },

      depth: {enable: false, mask: false}
    }

    Object.keys(args).forEach(function (x) {
      base[x] = args[x]
    })

    function runCheck (suffix) {
      var pixels = regl.read()
      var actual = new Array(64)
      for (var i = 0; i < 64; ++i) {
        actual[i] = Math.min(1, pixels[4 * i])
      }
      t.same(actual, expected, remark + ' - ' + suffix)
    }

    var command = regl(base)

    regl.clear({color: [0, 0, 0, 0]})
    command()
    runCheck('static')

    regl.clear({color: [0, 0, 0, 0]})
    command(1)
    runCheck('batch')

    regl.clear({color: [0, 0, 0, 0]})
    command(function () {
      regl.draw()
    })
    runCheck('scope')
  }

  // points
  checkPixmap({
    primitive: 'points',
    count: 4
  }, [
    1, 0, 0, 0, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    1, 0, 0, 0, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
  ], 'point')

  // lines
  checkPixmap({
    primitive: 'lines',
    count: 2
  }, [
    1, 1, 1, 1, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
  ], 'line')

  // line strip
  checkPixmap({
    primitive: 'line strip',
    count: 3
  }, [
    1, 1, 1, 1, 1, 0, 0, 0,
    0, 0, 0, 0, 1, 0, 0, 0,
    0, 0, 0, 0, 1, 0, 0, 0,
    0, 0, 0, 0, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
  ], 'line strip')

  // line loop
  checkPixmap({
    primitive: 'line loop',
    count: 4
  }, [
    1, 1, 1, 1, 1, 0, 0, 0,
    1, 0, 0, 0, 1, 0, 0, 0,
    1, 0, 0, 0, 1, 0, 0, 0,
    1, 0, 0, 0, 1, 0, 0, 0,
    1, 1, 1, 1, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
  ], 'line loop')

  // triangles
  checkPixmap({
    primitive: 'triangles',
    count: 3
  }, [
    1, 1, 1, 1, 0, 0, 0, 0,
    0, 1, 1, 1, 0, 0, 0, 0,
    0, 0, 1, 1, 0, 0, 0, 0,
    0, 0, 0, 1, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
  ], 'triangles')

  // triangle strip
  checkPixmap({
    primitive: 'triangle strip',
    count: 4
  }, [
    1, 1, 1, 1, 0, 0, 0, 0,
    0, 1, 1, 1, 0, 0, 0, 0,
    0, 0, 1, 1, 0, 0, 0, 0,
    0, 1, 1, 1, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
  ], 'triangle strip')

  // triangle fan
  checkPixmap({
    primitive: 'triangle fan',
    count: 4
  }, [
    1, 1, 1, 1, 0, 0, 0, 0,
    1, 1, 1, 1, 0, 0, 0, 0,
    1, 1, 1, 1, 0, 0, 0, 0,
    1, 1, 1, 1, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0
  ], 'triangle fan')

  regl.destroy()
  createContext.destroy(gl)
  t.end()
})
<|endoftext|>


<commit_before>'use strict';
/*jshint asi: true*/

var test = require('tap').test
  , hns = require('./utils/harness')()

  // TODO: testharness should no longer reset on seq, fix tests to still work and publish new test harness

test('given the line contains hello world', function (t) {
  function setup() {
    hns.reset()
    //              01234567890
    hns.rli.line = 'hello world'
  }

  t.test('and the cursor is at position 0', function (t) {
    hns.rli.cursor = 0

    hns.seq('f e')
    t.equal(hns.moveCursor.pop(), 1, hns.seqed + 'moves cursor to e')

    t.end()
  })

})
<commit_msg>finsishing find tests<commit_after>'use strict';
/*jshint asi: true*/

var test = require('tap').test
  , hns = require('./utils/harness')()

test('\ngiven the line contains hello world', function (t) {
  function setup() {
    hns.reset()
    //              01234567890
    hns.rli.line = 'hello world'
  }

  t.test('\n# and the cursor is at position 0', function (t) {
    function setupCursorAt_0() {
      setup()
      hns.rli.cursor = 0
    }

    // TODO: make space work

    setupCursorAt_0()
    hns.seq('f e')
    t.equal(hns.rli.moveCursor.pop(), 1, hns.seqed + 'moves cursor to e')

    setupCursorAt_0()
    hns.seq('f z')
    t.equal(hns.rli.moveCursor.length, 0, hns.seqed + 'does not move cursor')

    setupCursorAt_0()
    hns.seq('f l')
    t.equal(hns.rli.moveCursor.pop(), 2, hns.seqed + 'moves cursor to l')

    setupCursorAt_0()
    hns.seq('t l')
    t.equal(hns.rli.moveCursor.pop(), 1, hns.seqed + 'moves cursor up to l')

    t.end()
  })

  t.test('\n# and the cursor is at position 5', function (t) {
    function setupCursorAt_5() {
      setup()
      hns.rli.cursor = 5
    }

    setupCursorAt_5()
    hns.seq('f e')
    t.equal(hns.rli.moveCursor.length, 0, hns.seqed + 'does not move cursor')

    setupCursorAt_5()
    hns.seq('f d')
    t.equal(hns.rli.moveCursor.pop(), 5, hns.seqed + 'moves cursor to d')

    setupCursorAt_5()
    hns.seq('shift-f d')
    t.equal(hns.rli.moveCursor.length, 0, hns.seqed + 'does not move cursor')

    setupCursorAt_5()
    hns.seq('t d')
    t.equal(hns.rli.moveCursor.pop(), 4, hns.seqed + 'moves cursor up to d')

    setupCursorAt_5()
    hns.seq('shift-t d')
    t.equal(hns.rli.moveCursor.length, 0, hns.seqed + 'does not move cursor')

    setupCursorAt_5()
    hns.seq('shift-f e')
    t.equal(hns.rli.moveCursor.pop(), -4, hns.seqed + 'moves cursor to e')

    setupCursorAt_5()
    hns.seq('shift-t e')
    t.equal(hns.rli.moveCursor.pop(), -3, hns.seqed + 'moves cursor up to e')

    t.end()
  })
})
<|endoftext|>


<commit_before>'use strict';
require('webrtc-adapter');

var NextRTC = function NextRTC(config) {
    if (!(this instanceof NextRTC)) {
        return new NextRTC(config);
    }
    var that = this;
    this.mediaConfig = config.mediaConfig !== undefined ? config.mediaConfig : null;
    this.type = config.type;

    this.signaling = new WebSocket(config.wsURL);
    this.peerConnections = {};
    this.localStream = null;
    this.signals = {};

    this.call = function(event, data) {
        for ( var signal in this.signals) {
            if (event === signal) {
                return this.signals[event](this, data);
            }
        }
        console.log('Event ' + event + ' do not have defined function');
    };

    this.request = function(signal, to, convId, custom) {
        var req = JSON.stringify({
            signal: signal,
            to: to,
            content: convId,
            custom: custom });
        console.log("res: " + req);
        this.signaling.send(req);
    };

    this.signaling.onmessage = function(event) {
        console.log("req: " + event.data);
        var signal = JSON.parse(event.data);
        that.call(signal.signal, signal);
    };

    this.signaling.onclose = function(event) {
        that.call('close', event);
    };

    this.signaling.onerror = function(event) {
        that.call('error', event);
    };

    this.preparePeerConnection = function(nextRTC, member) {
        if (nextRTC.peerConnections[member] == undefined) {
            var pc = new RTCPeerConnection(config.peerConfig);
            pc.onaddstream = function(evt) {
                nextRTC.call('remoteStream', {
                    member : member,
                    stream : evt.stream
                });
            };
            pc.onicecandidate = function(evt) {
                handle(pc, evt);

                function handle(pc, evt){
                    if((pc.signalingState || pc.readyState) == 'stable'
                        && nextRTC.peerConnections[member]['rem'] == true){
                        nextRTC.onIceCandidate(nextRTC, member, evt);
                        return;
                    }
                    setTimeout(function(){ handle(pc, evt); }, 2000);
                }
            };
            nextRTC.peerConnections[member] = {}
            nextRTC.peerConnections[member]['pc'] = pc;
            nextRTC.peerConnections[member]['rem'] = false;
        }
        return nextRTC.peerConnections[member];
    };

    this.offerRequest = function(nextRTC, from) {
        nextRTC.offerResponse(nextRTC, from);
    };

    this.offerResponse = function(nextRTC, signal) {
        var pc = nextRTC.preparePeerConnection(nextRTC, signal.from);
        pc['pc'].addStream(nextRTC.localStream);
        pc['pc'].createOffer({offerToReceiveAudio: 1, offerToReceiveVideo: 1})
            .then(function(desc) {
                pc['pc'].setLocalDescription(desc)
                    .then(function() {
                        nextRTC.request('offerResponse', signal.from, desc.sdp);
                    }, that.error);
            });
    };

    this.answerRequest = function(nextRTC, signal) {
        nextRTC.answerResponse(nextRTC, signal);
    };

    this.answerResponse = function(nextRTC, signal) {
        var pc = nextRTC.preparePeerConnection(nextRTC, signal.from);
        pc['pc'].addStream(nextRTC.localStream);
        pc['pc'].setRemoteDescription(new RTCSessionDescription({
            type : 'offer',
            sdp : signal.content
        })).then(function() {
            pc['rem'] = true;
            pc['pc'].createAnswer().then(function(desc) {
                pc['pc'].setLocalDescription(desc).then(function() {
                    nextRTC.request('answerResponse', signal.from, desc.sdp);
                });
              });
          });
    };

    this.finalize = function(nextRTC, signal) {
        var pc = nextRTC.preparePeerConnection(nextRTC, signal.from);
        pc['pc'].setRemoteDescription(new RTCSessionDescription({
            type : 'answer',
            sdp : signal.content
        })).then(function(){
            pc['rem'] = true;
        });
    };

    this.close = function(nextRTC, event) {
        nextRTC.signaling.close();
        if(nextRTC.localStream != null){
            nextRTC.localStream.stop();
        }
    };

    this.candidate = function(nextRTC, signal) {
        var pc = nextRTC.preparePeerConnection(nextRTC, signal.from);
        pc['pc'].addIceCandidate(new RTCIceCandidate(JSON.parse(signal.content.replace(new RegExp('\'', 'g'), '"'))), that.success, that.error);
    }

    this.init = function() {
        this.on('offerRequest', this.offerRequest);
        this.on('answerRequest', this.answerRequest);
        this.on('finalize', this.finalize);
        this.on('candidate', this.candidate);
        this.on('close', this.close);
        this.on('error', this.error);
        this.on('ping', function(){});
    };

    this.onIceCandidate = function(nextRTC, member, event) {
        if (event.candidate) {
            nextRTC.request('candidate', member, JSON.stringify(event.candidate));
        }
    }

    this.init();

    this.error = function(arg){
        console.log('error: ' + arg);
    }

    this.success = function(arg){
        console.log('success: ' + arg);
    }

    that.onReady = function() {
        console.log('It is highly recommended to override method NextRTC.onReady');
    };

    if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', function() {
            that.onReady();
        });
    }
};

NextRTC.prototype.on = function on(signal, operation) {
    this.signals[signal] = operation;
};

NextRTC.prototype.create = function create(convId, custom) {
    var nextRTC = this;
    navigator.mediaDevices.getUserMedia(nextRTC.mediaConfig).then(function(stream) {
    nextRTC.localStream = stream;
    nextRTC.call('localStream', {
        stream : stream
    });
    nextRTC.request('create', null, convId, custom);
    }, this.error);
};

NextRTC.prototype.join = function join(convId, custom) {
    var nextRTC = this;
    navigator.mediaDevices.getUserMedia(nextRTC.mediaConfig).then(function(stream) {
        nextRTC.localStream = stream;
        nextRTC.call('localStream', {
            stream : stream
        });
        nextRTC.request('join', null, convId, custom);
    }, this.error);
};

NextRTC.prototype.leave = function leave() {
    var nextRTC = this;
    nextRTC.request('left');
    nextRTC.signaling.close();
    if(nextRTC.localStream != null){
        nextRTC.localStream.stop();
    }
};

module.exports.NextRTC = NextRTC;<commit_msg>added mechanism to collect request until websocket channel will be ready to transfer data<commit_after>'use strict';
require('webrtc-adapter');

var NextRTC = function NextRTC(config) {
    if (!(this instanceof NextRTC)) {
        return new NextRTC(config);
    }
    var that = this;
    this.mediaConfig = config.mediaConfig !== undefined ? config.mediaConfig : null;
    this.type = config.type;

    this.signaling = new WebSocket(config.wsURL);
    this.peerConnections = {};
    this.localStream = null;
    this.signals = {};
    this.channelReady = false;
    this.waiting = [];

    this.call = function(event, data) {
        for ( var signal in this.signals) {
            if (event === signal) {
                return this.signals[event](this, data);
            }
        }
        console.log('Event ' + event + ' do not have defined function');
    };

    this.request = function(signal, to, convId, custom) {
        var req = JSON.stringify({
            signal: signal,
            to: to,
            content: convId,
            custom: custom });
        if(!this.channelReady){
            this.waiting.push(req);
        } else {
            console.log("req: " + req);
            this.signaling.send(req);
        }
    };

    this.signaling.onmessage = function(event) {
        console.log("res: " + event.data);
        var signal = JSON.parse(event.data);
        that.call(signal.signal, signal);
    };

    this.signaling.onopen = function() {
        console.log("channel ready");
        that.setChannelReady();
    };

    this.signaling.onclose = function(event) {
        that.call('close', event);
    };

    this.signaling.onerror = function(event) {
        that.call('error', event);
    };

    this.setChannelReady = function(){
        for(var w in that.waiting){
            console.log("req: " + w);
            that.signaling.send(w);
        }
        that.channelReady = true;
    }

    this.preparePeerConnection = function(nextRTC, member) {
        if (nextRTC.peerConnections[member] == undefined) {
            var pc = new RTCPeerConnection(config.peerConfig);
            pc.onaddstream = function(evt) {
                nextRTC.call('remoteStream', {
                    member : member,
                    stream : evt.stream
                });
            };
            pc.onicecandidate = function(evt) {
                handle(pc, evt);

                function handle(pc, evt){
                    if((pc.signalingState || pc.readyState) == 'stable'
                        && nextRTC.peerConnections[member]['rem'] == true){
                        nextRTC.onIceCandidate(nextRTC, member, evt);
                        return;
                    }
                    setTimeout(function(){ handle(pc, evt); }, 2000);
                }
            };
            nextRTC.peerConnections[member] = {}
            nextRTC.peerConnections[member]['pc'] = pc;
            nextRTC.peerConnections[member]['rem'] = false;
        }
        return nextRTC.peerConnections[member];
    };

    this.offerRequest = function(nextRTC, from) {
        nextRTC.offerResponse(nextRTC, from);
    };

    this.offerResponse = function(nextRTC, signal) {
        var pc = nextRTC.preparePeerConnection(nextRTC, signal.from);
        pc['pc'].addStream(nextRTC.localStream);
        pc['pc'].createOffer({offerToReceiveAudio: 1, offerToReceiveVideo: 1})
            .then(function(desc) {
                pc['pc'].setLocalDescription(desc)
                    .then(function() {
                        nextRTC.request('offerResponse', signal.from, desc.sdp);
                    }, that.error);
            });
    };

    this.answerRequest = function(nextRTC, signal) {
        nextRTC.answerResponse(nextRTC, signal);
    };

    this.answerResponse = function(nextRTC, signal) {
        var pc = nextRTC.preparePeerConnection(nextRTC, signal.from);
        pc['pc'].addStream(nextRTC.localStream);
        pc['pc'].setRemoteDescription(new RTCSessionDescription({
            type : 'offer',
            sdp : signal.content
        })).then(function() {
            pc['rem'] = true;
            pc['pc'].createAnswer().then(function(desc) {
                pc['pc'].setLocalDescription(desc).then(function() {
                    nextRTC.request('answerResponse', signal.from, desc.sdp);
                });
              });
          });
    };

    this.finalize = function(nextRTC, signal) {
        var pc = nextRTC.preparePeerConnection(nextRTC, signal.from);
        pc['pc'].setRemoteDescription(new RTCSessionDescription({
            type : 'answer',
            sdp : signal.content
        })).then(function(){
            pc['rem'] = true;
        });
    };

    this.close = function(nextRTC, event) {
        nextRTC.signaling.close();
        if(nextRTC.localStream != null){
            nextRTC.localStream.stop();
        }
    };

    this.candidate = function(nextRTC, signal) {
        var pc = nextRTC.preparePeerConnection(nextRTC, signal.from);
        pc['pc'].addIceCandidate(new RTCIceCandidate(JSON.parse(signal.content.replace(new RegExp('\'', 'g'), '"'))), that.success, that.error);
    }

    this.init = function() {
        this.on('offerRequest', this.offerRequest);
        this.on('answerRequest', this.answerRequest);
        this.on('finalize', this.finalize);
        this.on('candidate', this.candidate);
        this.on('close', this.close);
        this.on('error', this.error);
        this.on('ping', function(){});
    };

    this.onIceCandidate = function(nextRTC, member, event) {
        if (event.candidate) {
            nextRTC.request('candidate', member, JSON.stringify(event.candidate));
        }
    }

    this.init();

    this.error = function(arg){
        console.log('error: ' + arg);
    }

    this.success = function(arg){
        console.log('success: ' + arg);
    }

    that.onReady = function() {
        console.log('It is highly recommended to override method NextRTC.onReady');
    };

    if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', function() {
            that.onReady();
        });
    }
};

NextRTC.prototype.on = function on(signal, operation) {
    this.signals[signal] = operation;
};

NextRTC.prototype.create = function create(convId, custom) {
    var nextRTC = this;
    navigator.mediaDevices.getUserMedia(nextRTC.mediaConfig).then(function(stream) {
    nextRTC.localStream = stream;
    nextRTC.call('localStream', {
        stream : stream
    });
    nextRTC.request('create', null, convId, custom);
    }, this.error);
};

NextRTC.prototype.join = function join(convId, custom) {
    var nextRTC = this;
    navigator.mediaDevices.getUserMedia(nextRTC.mediaConfig).then(function(stream) {
        nextRTC.localStream = stream;
        nextRTC.call('localStream', {
            stream : stream
        });
        nextRTC.request('join', null, convId, custom);
    }, this.error);
};

NextRTC.prototype.leave = function leave() {
    var nextRTC = this;
    nextRTC.request('left');
    nextRTC.signaling.close();
    if(nextRTC.localStream != null){
        nextRTC.localStream.stop();
    }
};

module.exports.NextRTC = NextRTC;<|endoftext|>


<commit_before>
describe('Main', function () {
  it('expectation', function () {
    expect(true).to.equal(true);
  });
});<commit_msg>Add some basic tests<commit_after>
describe('Main', function () {

  beforeEach(module('KeenTrackerModule'));

  describe('keenTrackerService', function () {
    var keenTrackerService, config;

    beforeEach(inject(function($injector) {
      keenTrackerService = $injector.get('keenTrackerService');

      config = {
        projectId: "",
        writeKey: "",
        readKey: ""
      }
    }));

    it('should exist', function () {
      expect(typeof keenTrackerService).toBe('object');
    });

    it('should have an initialize function', function () {
      expect(typeof keenTrackerService.initialize).toBe('function');
    });

    it('should have an add function', function() {
      expect(typeof keenTrackerService.add).toBe('function');
    });

  });

});<|endoftext|>


<commit_before>const ava = require('ava');
const { fs, tempFileLoc, tempDirLoc, tempFile, tempDir } = require('./lib');
const nextra = require('../src');

ava('standard usage', async test => {
	test.plan(2);
	const existing = tempFile();
	const move = tempFileLoc();
	await nextra.move(existing, move);

	await test.notThrowsAsync(fs.accessAsync(move));
	await test.throwsAsync(fs.accessAsync(existing));
});

ava('self', async test => {
	const existing = tempFile();
	test.deepEqual(await nextra.move(existing, existing, { overwrite: true }), await fs.accessAsync(existing));
});

ava('overwrite dir with file', async test => {
	const existing = tempFile();
	const move = tempDir();
	await test.throwsAsync(nextra.move(existing, move, { overwrite: true }));
});

ava('overwrite exiting file', async test => {
	test.plan(2);
	const existing = tempFile();
	const move = tempFile();
	await nextra.move(existing, move, { overwrite: true });

	await test.notThrowsAsync(fs.accessAsync(move));
	await test.throwsAsync(fs.accessAsync(existing));
});

ava('no overwrite', async test => {
	test.plan(2);
	const existing = tempFile();
	const move = tempFileLoc();
	await nextra.move(existing, move, { overwrite: false });

	await test.notThrowsAsync(fs.accessAsync(move));
	await test.throwsAsync(fs.accessAsync(existing));
});

ava('deep', async test => {
	test.plan(2);
	const existing = tempFile();
	const move = tempFileLoc(tempDirLoc());
	await nextra.move(existing, move, { mkdirp: true });

	await test.notThrowsAsync(fs.accessAsync(move));
	await test.throwsAsync(fs.accessAsync(existing));
});
<commit_msg>add another test case<commit_after>const ava = require('ava');
const { fs, tempFileLoc, tempDirLoc, tempFile, tempDir } = require('./lib');
const nextra = require('../src');

ava('standard usage', async test => {
	test.plan(2);
	const existing = tempFile();
	const move = tempFileLoc();
	await nextra.move(existing, move);

	await test.notThrowsAsync(fs.accessAsync(move));
	await test.throwsAsync(fs.accessAsync(existing));
});

ava('self', async test => {
	const existing = tempFile();
	test.deepEqual(await nextra.move(existing, existing, { overwrite: true }), await fs.accessAsync(existing));
});

ava('overwrite dir with file', async test => {
	const existing = tempFile();
	const move = tempDir();
	await test.throwsAsync(nextra.move(existing, move, { overwrite: true }));
});

ava('overwrite existing file', async test => {
	test.plan(2);
	const existing = tempFile();
	const move = tempFile();
	await nextra.move(existing, move, { overwrite: true });

	await test.notThrowsAsync(fs.accessAsync(move));
	await test.throwsAsync(fs.accessAsync(existing));
});

ava('no overwrite non-existent file', async test => {
	test.plan(2);
	const existing = tempFile();
	const move = tempFileLoc();
	await nextra.move(existing, move, { overwrite: false });

	await test.notThrowsAsync(fs.accessAsync(move));
	await test.throwsAsync(fs.accessAsync(existing));
});

ava('no overwrite existing file', async test => {
	const existing = tempFile();
	const move = tempFile();
	await test.throwsAsync(nextra.move(existing, move, { overwrite: false }));
});

ava('deep', async test => {
	test.plan(2);
	const existing = tempFile();
	const move = tempFileLoc(tempDirLoc());
	await nextra.move(existing, move, { mkdirp: true });

	await test.notThrowsAsync(fs.accessAsync(move));
	await test.throwsAsync(fs.accessAsync(existing));
});
<|endoftext|>


<commit_before>/*jslint forin: true */
var ref = require('ref');
var StructType = require('ref-struct');
var ArrayType = require('ref-array');

var node = StructType({
  edges: "pointer",

  edge_len: "uchar",
  compare_type: "uchar",
  endpoint: "uchar",
  ov_cnt: "uchar",

  edge_cap: "uchar",
  route_len: "uchar",
  route_cap: "uchar",

  pcre_pattern: "pointer",
  pcre_extra: "pointer",

  routes: "pointer",

  combined_pattern: "string",

  data: "pointer"
});

var route = StructType({
  path: "string",
  path_len: "int",

  request_method: "int",

  host: "string",
  host_len: "int",

  data: "pointer",

  remote_addr_pattern: "string",
  remote_addr_pattern_len: "int"
});

var StringArray = ArrayType("string");
var str_array = StructType({
  tokens: "pointer",
  len: "int",
  cap: "int"
});

var match_entry = StructType({
  vars: ref.refType(str_array),
  path: "string",
  path_len: "int",
  request_method: "int",

  data: "pointer",

  host: "pointer",
  host_len: "int",

  remote_addr: "pointer",
  remote_addr_len: "int"
});

// edge = StructType({
// pattern: "string",
// child: "pointer",
// pattern_len: "ushort",
// opcode: "uchar",
// has_slug: "uchar"
// });

const METHOD_GET = 2;
const METHOD_POST = 2<<1;
const METHOD_PUT = 2<<2;
const METHOD_DELETE = 2<<3;
const METHOD_PATCH = 2<<4;
const METHOD_HEAD = 2<<5;
const METHOD_OPTIONS = 2<<6;

const METHODS = {
  GET: METHOD_GET,
  POST: METHOD_POST,
  PUT: METHOD_PUT,
  DELETE: METHOD_DELETE,
  PATCH: METHOD_PATCH,
  HEAD: METHOD_HEAD,
  OPTIONS: METHOD_OPTIONS
};

var ffi = require('ffi');

var libr3 = ffi.Library('libr3', {
  "r3_tree_create": ["pointer", ["int"]],

  // node * r3_tree_insert_pathl_ex(node *tree, const char *path, int path_len, route * route, void * data, char ** errstr);
  "r3_tree_insert_pathl_ex": ["pointer", ["pointer", "string", "int", "pointer", "pointer", "pointer"]],

  // route * r3_tree_insert_routel_ex(node *tree, int method, const char *path, int path_len, void *data, char **errstr);
  "r3_tree_insert_routel_ex": ["pointer", ["pointer", "int", "string", "int", "pointer", "pointer"]],

  "r3_tree_compile": ["void", ["pointer"]],
  "r3_tree_dump": ["void", ["pointer", "int"]],

  // node * r3_tree_matchl(const node * n, const char * path, int path_len, match_entry * entry);
  "r3_tree_matchl": [ref.refType(node), ["pointer", "string", "int", "pointer"]],

  // route * r3_tree_match_route(const node *n, match_entry * entry);
  "r3_tree_match_route": [ref.refType(route), ["pointer", "pointer"]],

  "r3_tree_free": ["void", ["pointer"]],

  "match_entry_createl": [ref.refType(match_entry), ["string", "int"]],
});

var r3_tree_insert_path = function (tree, path, data) {
  return libr3.r3_tree_insert_pathl_ex(tree, path, path.length, null, data, null);
};

var r3_tree_insert_route = function (tree, method, path, data) {
  return libr3.r3_tree_insert_routel_ex(tree, method, path, path.length, data, null);
};

var match_entry_create = function (path) {
  return libr3.match_entry_createl(path, path.length);
};

var r3_tree_match = function (tree, path, entry) {
  return libr3.r3_tree_matchl(tree, path, path.length, entry);
};

var Router = function (routes) {
  var route, data, method, route_frag, i = 0;
  this.tree = libr3.r3_tree_create(10);
  this.data = [];
  for (route in routes) {
    this.data[i] = routes[route];
    data = new Buffer(4);
    data.writeUInt32LE(i, 0)
    route = route.trim();
    route_frag = route.split(' ');
    if (route_frag.length > 1) {
      route = route_frag[1];
      method = METHODS[route_frag[0].toUpperCase()];
      if (!method) { throw new Error(route_frag[0] + "method not exist."); }
      r3_tree_insert_route(this.tree, method, route, data);
    } else {
      r3_tree_insert_route(this.tree, 0, route, data);
    }
    i++;
  }
  libr3.r3_tree_compile(this.tree);
  return this;
};

Router.prototype.dump = function () {
  if (!this.tree) { return; }
  libr3.r3_tree_dump(this.tree, 0);
};

Router.prototype.match = function (path) {
  if (!this.tree) { return; }
  var entry;

  path = path.trim();
  var path_frag = path.split(' ');
  if (path_frag.length > 1) {
    path = path_frag[1];
    entry = match_entry_create(path);
    method = METHODS[path_frag[0].toUpperCase()];
    entry.deref().request_method = method;
  } else {
    entry = match_entry_create(path);
  }

  var node = libr3.r3_tree_match_route(this.tree, entry);

  if (ref.isNull(node)) { return; }

  var count = node.deref().data.reinterpret(4).readUInt32LE(0);
  var data = this.data[count];

  var vars = entry.deref().vars.deref();
  var capturesBuffer = new StringArray(vars.tokens.reinterpret(vars.len * ref.types.CString.size));
  var captures = [], i;
  for (i = 0; i < capturesBuffer.length; i++) {
    captures.push(capturesBuffer[i]);
  }

  return [data, captures];
};

Router.prototype.free = function () {
  if (!this.tree) { return; }
  libr3.r3_tree_free(this.tree);
  this.tree = null;
};

Router.prototype.httpHandler = function (err) {
  var self = this;
  return function(req, res) {
    var method = req.method;
    var path = req.url;
    var entry = method + " " + path;

    result = self.match(entry);

    if (result) {
      result[0].apply(this, [req, res, result[1]]);
    } else if (typeof err === 'function') {
      err(req, res);
    } else {
      res.end();
    }
  };
};

exports.new = function (routes) {
  return new Router(routes);
};

<commit_msg>Refine node-r3<commit_after>/*jslint forin: true */
var ref = require('ref');
var StructType = require('ref-struct');
var ArrayType = require('ref-array');

var node = StructType({
  edges: "pointer",

  edge_len: "uchar",
  compare_type: "uchar",
  endpoint: "uchar",
  ov_cnt: "uchar",

  edge_cap: "uchar",
  route_len: "uchar",
  route_cap: "uchar",

  pcre_pattern: "pointer",
  pcre_extra: "pointer",

  routes: "pointer",

  combined_pattern: "string",

  data: "pointer"
});

var route = StructType({
  path: "string",
  path_len: "int",

  request_method: "int",

  host: "string",
  host_len: "int",

  data: "pointer",

  remote_addr_pattern: "string",
  remote_addr_pattern_len: "int"
});

var StringArray = ArrayType("string");
var str_array = StructType({
  tokens: "pointer",
  len: "int",
  cap: "int"
});

var match_entry = StructType({
  vars: ref.refType(str_array),
  path: "string",
  path_len: "int",
  request_method: "int",

  data: "pointer",

  host: "pointer",
  host_len: "int",

  remote_addr: "pointer",
  remote_addr_len: "int"
});

// edge = StructType({
// pattern: "string",
// child: "pointer",
// pattern_len: "ushort",
// opcode: "uchar",
// has_slug: "uchar"
// });

const METHOD_GET = 2;
const METHOD_POST = 2<<1;
const METHOD_PUT = 2<<2;
const METHOD_DELETE = 2<<3;
const METHOD_PATCH = 2<<4;
const METHOD_HEAD = 2<<5;
const METHOD_OPTIONS = 2<<6;

const METHODS = {
  GET: METHOD_GET,
  POST: METHOD_POST,
  PUT: METHOD_PUT,
  DELETE: METHOD_DELETE,
  PATCH: METHOD_PATCH,
  HEAD: METHOD_HEAD,
  OPTIONS: METHOD_OPTIONS
};

var ffi = require('ffi');

var libr3 = ffi.Library('libr3', {
  "r3_tree_create": ["pointer", ["int"]],

  // node * r3_tree_insert_pathl_ex(node *tree, const char *path, int path_len, route * route, void * data, char ** errstr);
  "r3_tree_insert_pathl_ex": ["pointer", ["pointer", "string", "int", "pointer", "pointer", "pointer"]],

  // route * r3_tree_insert_routel_ex(node *tree, int method, const char *path, int path_len, void *data, char **errstr);
  "r3_tree_insert_routel_ex": ["pointer", ["pointer", "int", "string", "int", "pointer", "pointer"]],

  "r3_tree_compile": ["void", ["pointer"]],
  "r3_tree_dump": ["void", ["pointer", "int"]],

  // node * r3_tree_matchl(const node * n, const char * path, int path_len, match_entry * entry);
  "r3_tree_matchl": [ref.refType(node), ["pointer", "string", "int", "pointer"]],

  // route * r3_tree_match_route(const node *n, match_entry * entry);
  "r3_tree_match_route": [ref.refType(route), ["pointer", "pointer"]],

  "r3_tree_free": ["void", ["pointer"]],

  "match_entry_createl": [ref.refType(match_entry), ["string", "int"]],
  "match_entry_free": ["void", ["pointer"]],
});

var r3_tree_insert_path = function (tree, path, data) {
  return libr3.r3_tree_insert_pathl_ex(tree, path, path.length, null, data, null);
};

var r3_tree_insert_route = function (tree, method, path, data) {
  return libr3.r3_tree_insert_routel_ex(tree, method, path, path.length, data, null);
};

var match_entry_create = function (path) {
  return libr3.match_entry_createl(path, path.length);
};

var r3_tree_match = function (tree, path, entry) {
  return libr3.r3_tree_matchl(tree, path, path.length, entry);
};

var Router = function (routes) {
  var route, data, method, route_frag, i = 0;
  this.tree = libr3.r3_tree_create(10);
  this.data = [];
  for (route in routes) {
    this.data[i] = routes[route];
    data = ref.alloc('int', i).ref();
    route = route.trim();
    route_frag = route.split(' ');
    if (route_frag.length > 1) {
      route = route_frag[1];
      method = METHODS[route_frag[0].toUpperCase()];
      if (!method) { throw new Error(route_frag[0] + "method not exist."); }
      r3_tree_insert_route(this.tree, method, route, data);
    } else {
      r3_tree_insert_route(this.tree, 0, route, data);
    }
    i++;
  }
  libr3.r3_tree_compile(this.tree);
  return this;
};

Router.prototype.dump = function () {
  if (!this.tree) { return; }
  libr3.r3_tree_dump(this.tree, 0);
};

Router.prototype.match = function (path) {
  if (!this.tree) { return; }
  var entry;

  path = path.trim();
  var path_frag = path.split(' ');
  if (path_frag.length > 1) {
    path = path_frag[1];
    entry = match_entry_create(path);
    method = METHODS[path_frag[0].toUpperCase()];
    entry.deref().request_method = method;
  } else {
    entry = match_entry_create(path);
  }

  var node = libr3.r3_tree_match_route(this.tree, entry);

  if (ref.isNull(node)) { return; }

  var index = node.deref().data.reinterpret(8).readPointer(0, 4).readUInt32LE(0);
  var data = this.data[index];

  var vars = entry.deref().vars.deref();
  var capturesBuffer = new StringArray(vars.tokens.reinterpret(vars.len * ref.types.CString.size));
  var captures = [], i;
  for (i = 0; i < capturesBuffer.length; i++) {
    captures.push(capturesBuffer[i]);
  }

  libr3.match_entry_free(entry);
  return [data, captures];
};

Router.prototype.free = function () {
  if (!this.tree) { return; }
  libr3.r3_tree_free(this.tree);
  this.tree = null;
};

Router.prototype.httpHandler = function (err) {
  var self = this;
  return function(req, res) {
    var method = req.method;
    var path = req.url;
    var entry = method + " " + path;

    result = self.match(entry);

    if (result && typeof result[0] === 'function') {
      result[0].apply(this, [req, res, result[1]]);
    } else if (typeof err === 'function') {
      err(req, res);
    } else {
      res.end();
    }
  };
};

exports.new = function (routes) {
  return new Router(routes);
};

<|endoftext|>


<commit_before>/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
 * @toc {Database} Database
 * @namespace This object provides functions to manipulate client-side databases using SQL.
 *

 * The openDatabase() method on the Window and WorkerUtils can be used to get an instance of database. For example:

 * Database db=Window.openDatabase('documents', '1.0', 'Offline document storage', 5*1024*1024, null);
 *

 * Important Note: The HTML5 Database object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
Database ={
		/**
		 * @desc the current version of the database.
		 * @readOnly
		 * @type DOMString
		 * @PB10
		 * @BB50+
		 */
		version : "",

		/**
		 * @desc When called, this method immediately returns and then asynchronously runs the transaction steps with the transaction callback being the first argument, the error callback being the second argument, if any, the success callback being the third argument, if any, and with no preflight operation or postflight operation. The mode is read/write.
		 * @callback {function} callback Function to be called when executing SQL statements. Expected signature: function SQLTransactionCallback(SQLTransaction transaction).
		 * @callback {function} [errorCallback] Function to be called when SQL error occurs. Expected signature: function SQLTransactionErrorCallback(SQLError error).
		 * @callback {function} [successCallback] Function to be called when SQL statement is executed successfully. Expected signature: function SQLVoidCallback().
		 * @PB10
		 * @BB50+
		 */
		transaction : function(callback, errorCallback, successCallback){},

		/**
		 * @desc When called, this method immediately returns and then asynchronously runs the transaction steps with the transaction callback being the first argument, the error callback being the second argument, if any, the success callback being the third argument, if any, and with no preflight operation or postflight operation. The mode is read-only.
		 * @callback {function} callback Function to be called when executing SQL statements. Expected signature: function SQLTransactionCallback(SQLTransaction transaction).
		 * @callback {function} [errorCallback] Function to be called when SQL error occurs. Expected signature: function SQLTransactionErrorCallback(SQLError error).
		 * @callback {function} [successCallback] Function to be called when SQL statement is executed successfully. Expected signature: function SQLVoidCallback().
		 * @PB10
		 * @BB50+
		 * @example
		 * function showDocCount(db, span) {
  		 *	db.readTransaction(
  		 *		function (t) {
    	 *			t.executeSql('SELECT COUNT(*) AS c FROM docids', [],
    	 *				function (t, r) {
      	 *					span.textContent = r.rows[0].c;
      	 *				},
      	 *				function (t, e) {
      	 *					// couldn't read database
      	 *					span.textContent = '(unknown: ' + e.message + ')';
      	 *				}
      	 *			);
      	 *		}
      	 *	);
		 *}
		 *
		 */
		readTransaction : function(callback, errorCallback, successCallback){},

		/**
		 * @desc This method allows scripts to atomically verify the version number and change it at the same time as doing a schema update. When the method is invoked, it immediately returns, and then asynchronously runs the transaction steps with the transaction callback being the third argument, the error callback being the fourth argument, the success callback being the fifth argument. If any of the optional arguments are omitted, then they are treated as if they were null.
		 * @param  {DOMString} oldVersion database's current version.
		 * @param  {DOMString} newVersion database's new version.
		 * @callback {function} [callback] Function to be called when executing SQL statements. Expected signature: function SQLTransactionCallback(SQLTransaction transaction).
		 * @callback {function} [errorCallback] Function to be called when SQL error occurs. Expected signature: function SQLTransactionErrorCallback(SQLError error).
		 * @callback {function} [successCallback] Function to be called when SQL statement is executed successfully. Expected signature: function SQLVoidCallback().
		 * @PB10
		 * @BB50+
		 * @example
		 * db.changeVersion('', '1.0', function (t) {...});
		 *
		 */
		changeVersion : function(oldVersion, newVersion, callback, errorCallback, successCallback){}
};

/**
 * @toc {Database} SQLTransaction
 * @namespace
 *

 * Important Note: The HTML5 SQLTransaction object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
SQLTransaction = {
		/**
		 * @desc This method executes the provided SQL statement
		 * @param {DOMString} sqlStatement the SQL statement
		 * @param {ObjectArray} [arguments] the optional arguments used to preprocess a SQL statement by binding each ? placeholder with the value of the argument in the arguments array with the same position.
		 * @param {function} [callback] Function to be called when statement's result set is ready. Expected signature: function SQLStatementCallback (SQLTransaction transaction, SQLResultSet resultSet).
		 * @param {function} [errorCallback] Function to be called when SQL error occurs. Expected signature: function SQLStatementErrorCallback (SQLTransaction transaction, SQLError error).
		 * @PB10
		 * @BB50+
		 * @example
		 * function showDocCount(db, span) {
  		 *	db.readTransaction(
  		 *		function (t) {
    	 *			t.executeSql('SELECT COUNT(*) AS c FROM docids', [],
    	 *				function (t, r) {
      	 *					span.textContent = r.rows[0].c;
      	 *				},
      	 *				function (t, e) {
      	 *					// couldn't read database
      	 *					span.textContent = '(unknown: ' + e.message + ')';
      	 *				}
      	 *			);
      	 *		}
      	 *	);
		 *}
		 *
		 */
		executeSql : function(sqlStatement, arguments, callback, errorCallback) {}
};

/**
 * @toc {Database} SQLResultSet
 * @namespace
 *

 * Important Note: The HTML5 SQLResultSet object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
SQLResultSet = {
		/**
		 * @desc If the SQL statement inserted a row, this attribute returns the row ID of the row that the SQLResultSet object's SQL statement inserted into the database. If the SQL statement inserted multiple rows, this attribute returns the the ID of the last row.
		 * @readOnly
		 * @type long
		 * @PB10
		 * @BB50+
		 */
		insertId : 0,

		/**
		 * @desc This attribute returns the number of rows that were changed by the SQL statement. If the statement did not affected any rows, 0 is returned.
		 * @readOnly
		 * @type long
		 * @PB10
		 * @BB50+
		 */
		rowsAffected : 0,

		/**
		 * @desc This attribute represents the rows returned in the order returned by the database.If no rows were returned, then the object will be empty (its length will be zero).
		 * @readOnly
		 * @type SQLResultSetRowList
		 * @PB10
		 * @BB50+
		 */
		rows : null

};

/**
 * @toc {Database} SQLResultSetRowList
 * @namespace
 *

 * Important Note: The HTML5 SQLResultSetRowList object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
SQLResultSetRowList = {
		/**
		 * @desc the number of rows returned by the database.
		 * @readOnly
		 * @type unsigned long
		 * @PB10
		 * @BB50+
		 */
		length : 0,

		/**
		 * @desc return the row with the given index.
		 * @param {unsigned long} index the index
		 * @returns {Object} the row with the given index. If there is no such row, return null.
		 * @PB10
		 * @BB50+
		 */
		item : function(index) {}
};

/**
 * @toc {Database} SQLError
 * @namespace Errors in the asynchronous database API are reported using callbacks that have a SQLError object as one of their arguments.
 *

 * Important Note: The HTML5 SQLError object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
SQLError = {
		/**
		 * @constant
		 * @type Number
		 * @desc The transaction failed for reasons unrelated to the database itself and not covered by any other error code.
		 * @PB10
		 * @BB50+
		 * @default 0
		 */
		UNKNOWN_ERR : 0,

		/**
		 * @constant
		 * @type Number
		 * @desc The statement failed for database reasons not covered by any other error code.
		 * @PB10
		 * @BB50+
		 * @default 1
		 */
		DATABASE_ERR : 1,

		/**
		 * @constant
		 * @type Number
		 * @desc The operation failed because the actual database version was not what it should be.
		 * @PB10
		 * @BB50+
		 * @default 2
		 */
		VERSION_ERR : 2,

		/**
		 * @constant
		 * @type Number
		 * @desc The statement failed because the data returned from the database was too large. The SQL "LIMIT" modifier might be useful to reduce the size of the result set.
		 * @PB10
		 * @BB50+
		 * @default 3
		 */
		TOO_LARGE_ERR : 3,

		/**
		 * @constant
		 * @type Number
		 * @desc The statement failed because there was not enough remaining storage space, or the storage quota was reached and the user declined to give more space to the database.
		 * @PB10
		 * @BB50+
		 * @default 4
		 */
		QUOTA_ERR : 4,

		/**
		 * @constant
		 * @type Number
		 * @desc The statement failed because of a syntax error, or the number of arguments did not match the number of ? placeholders in the statement, or the statement tried to use a statement that is not allowed, such as BEGIN, COMMIT, or ROLLBACK, or the statement tried to use a verb that could modify the database but the transaction was read-only.
		 * @PB10
		 * @BB50+
		 * @default 5
		 */
		SYNTAX_ERR : 5,

		/**
		 * @constant
		 * @type Number
		 * @desc An INSERT, UPDATE, or REPLACE statement failed due to a constraint failure. For example, because a row was being inserted and the value given for the primary key column duplicated the value of an existing row.
		 * @PB10
		 * @BB50+
		 * @default 6
		 */
		CONSTRAINT_ERR : 6,

		/**
		 * @constant
		 * @type Number
		 * @desc A lock for the transaction could not be obtained in a reasonable time.
		 * @PB10
		 * @BB50+
		 * @default 7
		 */
		TIMEOUT_ERR : 7,

		/**
		 * @desc the most appropriate error code
		 * @readOnly
		 * @type unsigned short
		 * @PB10
		 * @BB50+
		 */
		code : 0,

		/**
		 * @desc an error message describing the error encountered. The message should be localized to the user's language.
		 * @readOnly
		 * @type DOMString
		 * @PB10
		 * @BB50+
		 */
		message : ""
};
<commit_msg>remove WorkerUtils from header description since its openDatabase method is not supported in BB and PB<commit_after>/*
* Copyright 2010-2011 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
 * @toc {Database} Database
 * @namespace This object provides functions to manipulate client-side databases using SQL.
 *

 * The openDatabase() method on the Window can be used to get an instance of database. For example:

 * Database db=Window.openDatabase('documents', '1.0', 'Offline document storage', 5*1024*1024, null);
 *

 * Important Note: The HTML5 Database object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
Database ={
		/**
		 * @desc the current version of the database.
		 * @readOnly
		 * @type DOMString
		 * @PB10
		 * @BB50+
		 */
		version : "",

		/**
		 * @desc When called, this method immediately returns and then asynchronously runs the transaction steps with the transaction callback being the first argument, the error callback being the second argument, if any, the success callback being the third argument, if any, and with no preflight operation or postflight operation. The mode is read/write.
		 * @callback {function} callback Function to be called when executing SQL statements. Expected signature: function SQLTransactionCallback(SQLTransaction transaction).
		 * @callback {function} [errorCallback] Function to be called when SQL error occurs. Expected signature: function SQLTransactionErrorCallback(SQLError error).
		 * @callback {function} [successCallback] Function to be called when SQL statement is executed successfully. Expected signature: function SQLVoidCallback().
		 * @PB10
		 * @BB50+
		 */
		transaction : function(callback, errorCallback, successCallback){},

		/**
		 * @desc When called, this method immediately returns and then asynchronously runs the transaction steps with the transaction callback being the first argument, the error callback being the second argument, if any, the success callback being the third argument, if any, and with no preflight operation or postflight operation. The mode is read-only.
		 * @callback {function} callback Function to be called when executing SQL statements. Expected signature: function SQLTransactionCallback(SQLTransaction transaction).
		 * @callback {function} [errorCallback] Function to be called when SQL error occurs. Expected signature: function SQLTransactionErrorCallback(SQLError error).
		 * @callback {function} [successCallback] Function to be called when SQL statement is executed successfully. Expected signature: function SQLVoidCallback().
		 * @PB10
		 * @BB50+
		 * @example
		 * function showDocCount(db, span) {
  		 *	db.readTransaction(
  		 *		function (t) {
    	 *			t.executeSql('SELECT COUNT(*) AS c FROM docids', [],
    	 *				function (t, r) {
      	 *					span.textContent = r.rows[0].c;
      	 *				},
      	 *				function (t, e) {
      	 *					// couldn't read database
      	 *					span.textContent = '(unknown: ' + e.message + ')';
      	 *				}
      	 *			);
      	 *		}
      	 *	);
		 *}
		 *
		 */
		readTransaction : function(callback, errorCallback, successCallback){},

		/**
		 * @desc This method allows scripts to atomically verify the version number and change it at the same time as doing a schema update. When the method is invoked, it immediately returns, and then asynchronously runs the transaction steps with the transaction callback being the third argument, the error callback being the fourth argument, the success callback being the fifth argument. If any of the optional arguments are omitted, then they are treated as if they were null.
		 * @param  {DOMString} oldVersion database's current version.
		 * @param  {DOMString} newVersion database's new version.
		 * @callback {function} [callback] Function to be called when executing SQL statements. Expected signature: function SQLTransactionCallback(SQLTransaction transaction).
		 * @callback {function} [errorCallback] Function to be called when SQL error occurs. Expected signature: function SQLTransactionErrorCallback(SQLError error).
		 * @callback {function} [successCallback] Function to be called when SQL statement is executed successfully. Expected signature: function SQLVoidCallback().
		 * @PB10
		 * @BB50+
		 * @example
		 * db.changeVersion('', '1.0', function (t) {...});
		 *
		 */
		changeVersion : function(oldVersion, newVersion, callback, errorCallback, successCallback){}
};

/**
 * @toc {Database} SQLTransaction
 * @namespace
 *

 * Important Note: The HTML5 SQLTransaction object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
SQLTransaction = {
		/**
		 * @desc This method executes the provided SQL statement
		 * @param {DOMString} sqlStatement the SQL statement
		 * @param {ObjectArray} [arguments] the optional arguments used to preprocess a SQL statement by binding each ? placeholder with the value of the argument in the arguments array with the same position.
		 * @param {function} [callback] Function to be called when statement's result set is ready. Expected signature: function SQLStatementCallback (SQLTransaction transaction, SQLResultSet resultSet).
		 * @param {function} [errorCallback] Function to be called when SQL error occurs. Expected signature: function SQLStatementErrorCallback (SQLTransaction transaction, SQLError error).
		 * @PB10
		 * @BB50+
		 * @example
		 * function showDocCount(db, span) {
  		 *	db.readTransaction(
  		 *		function (t) {
    	 *			t.executeSql('SELECT COUNT(*) AS c FROM docids', [],
    	 *				function (t, r) {
      	 *					span.textContent = r.rows[0].c;
      	 *				},
      	 *				function (t, e) {
      	 *					// couldn't read database
      	 *					span.textContent = '(unknown: ' + e.message + ')';
      	 *				}
      	 *			);
      	 *		}
      	 *	);
		 *}
		 *
		 */
		executeSql : function(sqlStatement, arguments, callback, errorCallback) {}
};

/**
 * @toc {Database} SQLResultSet
 * @namespace
 *

 * Important Note: The HTML5 SQLResultSet object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
SQLResultSet = {
		/**
		 * @desc If the SQL statement inserted a row, this attribute returns the row ID of the row that the SQLResultSet object's SQL statement inserted into the database. If the SQL statement inserted multiple rows, this attribute returns the the ID of the last row.
		 * @readOnly
		 * @type long
		 * @PB10
		 * @BB50+
		 */
		insertId : 0,

		/**
		 * @desc This attribute returns the number of rows that were changed by the SQL statement. If the statement did not affected any rows, 0 is returned.
		 * @readOnly
		 * @type long
		 * @PB10
		 * @BB50+
		 */
		rowsAffected : 0,

		/**
		 * @desc This attribute represents the rows returned in the order returned by the database.If no rows were returned, then the object will be empty (its length will be zero).
		 * @readOnly
		 * @type SQLResultSetRowList
		 * @PB10
		 * @BB50+
		 */
		rows : null

};

/**
 * @toc {Database} SQLResultSetRowList
 * @namespace
 *

 * Important Note: The HTML5 SQLResultSetRowList object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
SQLResultSetRowList = {
		/**
		 * @desc the number of rows returned by the database.
		 * @readOnly
		 * @type unsigned long
		 * @PB10
		 * @BB50+
		 */
		length : 0,

		/**
		 * @desc return the row with the given index.
		 * @param {unsigned long} index the index
		 * @returns {Object} the row with the given index. If there is no such row, return null.
		 * @PB10
		 * @BB50+
		 */
		item : function(index) {}
};

/**
 * @toc {Database} SQLError
 * @namespace Errors in the asynchronous database API are reported using callbacks that have a SQLError object as one of their arguments.
 *

 * Important Note: The HTML5 SQLError object is marked as supported for OS 5.0.  This support is accomplished by using the HTML5 JavaScript toolkit for BlackBerry OS 5.0.
 * @PB10
 * @BB50+
 */
SQLError = {
		/**
		 * @constant
		 * @type Number
		 * @desc The transaction failed for reasons unrelated to the database itself and not covered by any other error code.
		 * @PB10
		 * @BB50+
		 * @default 0
		 */
		UNKNOWN_ERR : 0,

		/**
		 * @constant
		 * @type Number
		 * @desc The statement failed for database reasons not covered by any other error code.
		 * @PB10
		 * @BB50+
		 * @default 1
		 */
		DATABASE_ERR : 1,

		/**
		 * @constant
		 * @type Number
		 * @desc The operation failed because the actual database version was not what it should be.
		 * @PB10
		 * @BB50+
		 * @default 2
		 */
		VERSION_ERR : 2,

		/**
		 * @constant
		 * @type Number
		 * @desc The statement failed because the data returned from the database was too large. The SQL "LIMIT" modifier might be useful to reduce the size of the result set.
		 * @PB10
		 * @BB50+
		 * @default 3
		 */
		TOO_LARGE_ERR : 3,

		/**
		 * @constant
		 * @type Number
		 * @desc The statement failed because there was not enough remaining storage space, or the storage quota was reached and the user declined to give more space to the database.
		 * @PB10
		 * @BB50+
		 * @default 4
		 */
		QUOTA_ERR : 4,

		/**
		 * @constant
		 * @type Number
		 * @desc The statement failed because of a syntax error, or the number of arguments did not match the number of ? placeholders in the statement, or the statement tried to use a statement that is not allowed, such as BEGIN, COMMIT, or ROLLBACK, or the statement tried to use a verb that could modify the database but the transaction was read-only.
		 * @PB10
		 * @BB50+
		 * @default 5
		 */
		SYNTAX_ERR : 5,

		/**
		 * @constant
		 * @type Number
		 * @desc An INSERT, UPDATE, or REPLACE statement failed due to a constraint failure. For example, because a row was being inserted and the value given for the primary key column duplicated the value of an existing row.
		 * @PB10
		 * @BB50+
		 * @default 6
		 */
		CONSTRAINT_ERR : 6,

		/**
		 * @constant
		 * @type Number
		 * @desc A lock for the transaction could not be obtained in a reasonable time.
		 * @PB10
		 * @BB50+
		 * @default 7
		 */
		TIMEOUT_ERR : 7,

		/**
		 * @desc the most appropriate error code
		 * @readOnly
		 * @type unsigned short
		 * @PB10
		 * @BB50+
		 */
		code : 0,

		/**
		 * @desc an error message describing the error encountered. The message should be localized to the user's language.
		 * @readOnly
		 * @type DOMString
		 * @PB10
		 * @BB50+
		 */
		message : ""
};
<|endoftext|>


<commit_before>/**
* Address.js
*
* @description :: TODO: You might write a short summary of how this model works and what it represents here.
* @docs        :: http://sailsjs.org/#!documentation/models
*/

module.exports = {

  attributes: {
    country : {
      type : 'string'
    },
    state : {
      type : 'string'
    },
    city : {
      type : 'string'
    },
    postcode : {
      type : 'number'
    },
    street : {
      type : 'string'
    },
    streetNumber : {
      type : 'number'
    }
  }
};
<commit_msg>postcode can be string<commit_after>/**
* Address.js
*
* @description :: TODO: You might write a short summary of how this model works and what it represents here.
* @docs        :: http://sailsjs.org/#!documentation/models
*/

module.exports = {

  attributes: {
    country : {
      type : 'string'
    },
    state : {
      type : 'string'
    },
    city : {
      type : 'string'
    },
    postcode : {
      type : 'string'
    },
    street : {
      type : 'string'
    },
    streetNumber : {
      type : 'number'
    }
  }
};
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var PatternRow = require('./pattern-row');

var factory = null;
module.exports = function(app) {

	if (factory) return factory;

	var modelName = 'pattern';
	var schema = mongoose.Schema({
		parent_id: String,
		name: String,
		length: {type: Number, default: 16},
		locked: Boolean,
		rows: [PatternRow]  // breaks lots of tests. does this explain the [Object object] cast in generic save?
	});
	require('./schema-id')(schema);
	factory = mongoose.model(modelName, schema);

	return factory;
};
<commit_msg>Revert embedded doc change.<commit_after>var mongoose = require('mongoose');

var factory = null;
module.exports = function(app) {

	if (factory) return factory;

	var modelName = 'pattern';
	var schema = mongoose.Schema({
		parent_id: String,
		name: String,
		length: {type: Number, default: 16},
		locked: Boolean,
		rows: [{type: String, ref: 'pattern-row'}]
	});
	require('./schema-id')(schema);
	factory = mongoose.model(modelName, schema);

	return factory;
};
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2014 Scott Beck, all rights reserved
 *
 * Licensed under the MIT license
 *
 */
(function () {
  "use strict";
  function section(docs, docsLine, code, codeLine) {
    return {
      docsText: docs,
      docsLine: docsLine,
      codeText: code,
      codeLine: codeLine
    };
  }
  describe("part#exports", function () {
    it("should load without throwing errors", function () {
      (function () { require("../index.js"); })
        .should.not.throw();
    });
    it("should be a function", function () {
      require("../index.js")
        .should.be.a('function');
    });
    it("should take 3 arguments", function () {
      require("../index.js").length
        .should.equal(3);
    });
    it("should throw Error with no args", function () {
      (function () { require("../index.js")(); })
        .should.throw(Error);
    });
  });
  describe("part#Interface", function () {
    beforeEach(function () {
      this.part = require("../index.js");
    });
    // XXX docco adds a new line to the end of the
    // last section.
    describe("docco", function () {
      it("should extract empty", function () {
        expect(this.part('t1.js', ""))
          .to.deep.equal([section("", 1, "\n", 1)]);
      });
      it("should extract comment", function () {
        expect(this.part('t1.js', "// t1"))
          .to.deep.equal([section("t1\n", 1, "", 2)]);
      });
      it("should extract code", function () {
        expect(this.part('t1.js', "var code = 1;"))
          .to.deep.equal([section("", 1, "var code = 1;\n", 1)]);
      });
      it("should extract comment|code", function () {
        expect(this.part('t1.js', "// t1\ncode = 1;"))
          .to.deep.equal([section("t1\n", 1, "code = 1;\n", 2)]);
      });
      it("should extract code|comment", function () {
        expect(this.part('t1.js', "var code = 'foo';\n// t1"))
          .to.deep.equal([section("", 1, "var code = 'foo';\n", 1), section("t1\n", 2, "", 3)]);
      });
      it("should extract comment|comment", function () {
        expect(this.part('t1.js', "// t1\n// t2"))
          .to.deep.equal([section("t1\nt2\n", 1, "", 3)]);
      });
      it("should extract code|code", function () {
        expect(this.part('t1.js', "var foo = 1,\n\tbar = 2;"))
          .to.deep.equal([section("", 1, "var foo = 1,\n\tbar = 2;\n", 1)]);
      });
      it("should extract comment|code|comment", function () {
        expect(this.part('t1.js', "// t1\ncode=1;\n// t2"))
          .to.deep.equal([section("t1\n", 1, "code=1;\n", 2), section("t2\n", 3, "", 4)]);
      });
      it("should extract comment|code|comment|code", function () {
        expect(this.part('t1.js', "// t1\ncode=1;\n// t2\nvar foo = 1;"))
          .to.deep.equal([section("t1\n", 1, "code=1;\n", 2), section("t2\n", 3, "var foo = 1;\n", 4)]);
      });
      it("should extract code|comment|code|comment|code", function () {
        expect(this.part('t1.js', "// t1\ncode=1;\n// t2\nvar foo = 1;"))
          .to.deep.equal([section("t1\n", 1, "code=1;\n", 2), section("t2\n", 3, "var foo = 1;\n", 4)]);
      });
      it("should load from file", function () {
        expect(this.part('./test/t1.js'))
          .to.deep.equal([
            section("", 1, "(function () {\n  'use strict';\n", 1),
            section("comment1\n", 3, "  var code1 = 1;\n", 4),
            section("comment2\n", 5, "  var code2 = 2;\n})();\n\n", 6)
          ]);
      });
    });
    describe("htmlParser", function () {
      it("should extract empty", function () {
        expect(this.part('t1.html', ""))
          .to.deep.equal([section("", 1, '', 1)]);
      });
      it("should extract comment", function () {
        expect(this.part('t1.html', ""))
          .to.deep.equal([section("t1\n", 1, '', 2)]);
      });
      it("should extract code", function () {
        expect(this.part('t1.html', "

"))
          .to.deep.equal([section("", 1, "

", 1)]);
      });
      it("should extract comment|code", function () {
        expect(this.part('t1.html', "\n"))
          .to.deep.equal([section("t1", 1, "\n", 2)]);
      });
      it("should extract code|comment", function () {
        expect(this.part('t1.html', "\n"))
          .to.deep.equal([section("", 1, "\n", 1), section("foo bar baz", 2, "", 2)]);
      });
      it("should extract comment|comment", function () {
        expect(this.part('t1.html', ""))
          .to.deep.equal([section("t1", 1, "", 1), section("t2", 1, "", 1)]);
      });
      it("should extract code|code", function () {
        expect(this.part('t1.html', "
\n\t
foo
\n
"))
          .to.deep.equal([section("", 1, "
\n\t
foo
\n
", 1)]);
      });
      it("should extract comment|code|comment", function () {
        expect(this.part('t1.html', "\n"))
          .to.deep.equal([section("t1", 1, "\n", 2), section("t2", 2, "", 2)]);
      });
      it("should extract comment|code|comment|code", function () {
        expect(this.part('t1.html', "
\n\n
\n"))
          .to.deep.equal([section("t1", 1, "
\n", 1), section("t2", 2, "\n
\n", 3)]);
      });
      it("should skip directives", function () {
        expect(this.part('t.html', "
\n
"))
          .to.deep.equal([section("", 1, "
\n
", 1)]);
      });
      it("should explicitly skip directives", function () {
        expect(this.part('t.html', "
\n
", {noSkipDirectives: false}))
          .to.deep.equal([section("", 1, "
\n
", 1)]);
      });
      it("should not skip directives", function () {
        expect(this.part('t.html', "
\n
", {noSkipDirectives: true}))
          .to.deep.equal([section("", 1, "
\n", 1), section("[if foo]", 2, "
", 2)]);
      });
      it("should respect new extension", function () {
        expect(this.part('t1.foo', "\n", {htmlParserExt: '.foo'}))
          .to.deep.equal([section("t1", 1, "\n", 2)]);
      });
    });
  });
})();
<commit_msg>test updates for litcoffee<commit_after>/*
 * Copyright (C) 2014 Scott Beck, all rights reserved
 *
 * Licensed under the MIT license
 *
 */
(function () {
  "use strict";
  function section(docs, docsLine, code, codeLine) {
    return {
      docsText: docs,
      docsLine: docsLine,
      codeText: code,
      codeLine: codeLine
    };
  }
  describe("part#exports", function () {
    it("should load without throwing errors", function () {
      (function () { require("../index.js"); })
        .should.not.throw();
    });
    it("should be a function", function () {
      require("../index.js")
        .should.be.a('function');
    });
    it("should take 3 arguments", function () {
      require("../index.js").length
        .should.equal(3);
    });
    it("should throw Error with no args", function () {
      (function () { require("../index.js")(); })
        .should.throw(Error);
    });
  });
  describe("part#Interface", function () {
    beforeEach(function () {
      this.part = require("../index.js");
    });
    describe("lineBased", function () {
      it("should extract empty", function () {
        expect(this.part('t1.js', ""))
          .to.deep.equal([]);
      });
      it("should extract literate empty", function () {
        expect(this.part('t1.litcoffee', ""))
          .to.deep.equal([]);
      });
      it("should extract comment", function () {
        expect(this.part('Cakefile', "# t1"))
          .to.deep.equal([section("t1", 1, "", 1)]);
      });
      it("should extract literate comment", function () {
        expect(this.part('t1.litcoffee', "t1"))
          .to.deep.equal([section("t1", 1, "", 1)]);
      });
      it("should extract code", function () {
        expect(this.part('t1.js', "var code = 1;"))
          .to.deep.equal([section("", 1, "var code = 1;", 1)]);
      });
      it("should extract literate code", function () {
        expect(this.part('t1.litcoffee', "\tcode = 1"))
          .to.deep.equal([section("", 1, "code = 1", 1)]);
      });
      it("should extract comment|code", function () {
        expect(this.part('t1.js', "// t1\ncode = 1;"))
          .to.deep.equal([section("t1\n", 1, "code = 1;", 2)]);
      });
      it("should extract literate comment|code", function () {
        expect(this.part('t1.litcoffee', "t1\n\n\tcode = 1"))
          .to.deep.equal([section("t1\n\n", 1, "code = 1", 3)]);
      });
      it("should extract code|comment", function () {
        expect(this.part('Cakefile', "code = 'foo';\n# t1"))
          .to.deep.equal([section("", 1, "code = 'foo';\n", 1), section("t1", 2, "", 2)]);
      });
      it("should extract literate code|comment", function () {
        expect(this.part('t1.litcoffee', "\tcode = 'foo'\n\nt1"))
          .to.deep.equal([section("", 1, "code = 'foo'\n\n", 1), section("t1", 3, "", 3)]);
      });
      it("should extract comment|comment", function () {
        expect(this.part('t1.js', "// t1\n// t2"))
          .to.deep.equal([section("t1\nt2", 1, "", 2)]);
      });
      it("should extract literate comment|comment", function () {
        expect(this.part('t1.litcoffee', "t1\nt2"))
          .to.deep.equal([section("t1\nt2", 1, "", 2)]);
      });
      it("should extract code|code", function () {
        expect(this.part('t1.js', "var foo = 1,\n\tbar = 2;"))
          .to.deep.equal([section("", 1, "var foo = 1,\n    bar = 2;", 1)]);
      });
      it("should extract literate code|code", function () {
        expect(this.part('t1.litcoffee', "\tfoo = 1,\n\tbar = 2"))
          .to.deep.equal([section("", 1, "foo = 1,\nbar = 2", 1)]);
      });
      it("should extract comment|code|comment", function () {
        expect(this.part('t1.js', "// t1\ncode=1;\n// t2"))
          .to.deep.equal([section("t1\n", 1, "code=1;\n", 2), section("t2", 3, "", 3)]);
      });
      it("should extract literate comment|code|comment", function () {
        expect(this.part('t1.litcoffee', "t1\n\n    code=1\n\nt2"))
          .to.deep.equal([section("t1\n\n", 1, "code=1\n\n", 3), section("t2", 5, "", 5)]);
      });
      it("should extract comment|code|comment|code", function () {
        expect(this.part('t1.js', "// t1\ncode=1;\n// t2\nvar foo = 1;"))
          .to.deep.equal([section("t1\n", 1, "code=1;\n", 2), section("t2\n", 3, "var foo = 1;", 4)]);
      });
      it("should extract literate comment|code|comment|code", function () {
        expect(this.part('t1.litcoffee', "t1\n\n\tcode=1\n\nt2\n\n\tfoo = 1"))
          .to.deep.equal([section("t1\n\n", 1, "code=1\n\n", 3), section("t2\n\n", 5, "foo = 1", 7)]);
      });
      it("should extract code|comment|code|comment|code", function () {
        expect(this.part('t1.js', "// t1\ncode=1;\n// t2\nvar foo = 1;"))
          .to.deep.equal([section("t1\n", 1, "code=1;\n", 2), section("t2\n", 3, "var foo = 1;", 4)]);
      });
      it("should extract literate code|comment|code|comment|code", function () {
        expect(this.part('t1.litcoffee', "t1\n\n\tcode=1\n\nt2\n\n\tfoo = 1"))
          .to.deep.equal([section("t1\n\n", 1, "code=1\n\n", 3), section("t2\n\n", 5, "foo = 1", 7)]);
      });
      it("should end doc", function () {
        expect(this.part('t1.js', "// t1\ncode=1;\n//----\nvar foo = 1;"))
          .to.deep.equal([section("t1\n", 1, "code=1;\n", 2), section("----\n", 3, "", 4), section("", 4, "var foo = 1;", 4)]);
      });
      it("should load from file", function () {
        expect(this.part('./test/t1.js'))
          .to.deep.equal([
            section("", 1, "(function () {\n  'use strict';\n", 1),
            section("comment1\n", 3, "  var code1 = 1;\n", 4),
            section("comment2\n", 5, "  var code2 = 2;\n})();\n", 6)
          ]);
      });
    });
    describe("htmlParser", function () {
      it("should extract empty", function () {
        expect(this.part('t1.html', ""))
          .to.deep.equal([section("", 1, '', 1)]);
      });
      it("should extract comment", function () {
        expect(this.part('t1.html', ""))
          .to.deep.equal([section("t1\n", 1, '', 2)]);
      });
      it("should extract code", function () {
        expect(this.part('t1.html', "

"))
          .to.deep.equal([section("", 1, "

", 1)]);
      });
      it("should extract comment|code", function () {
        expect(this.part('t1.html', "\n"))
          .to.deep.equal([section("t1", 1, "\n", 2)]);
      });
      it("should extract code|comment", function () {
        expect(this.part('t1.html', "\n"))
          .to.deep.equal([section("", 1, "\n", 1), section("foo bar baz", 2, "", 2)]);
      });
      it("should extract comment|comment", function () {
        expect(this.part('t1.html', ""))
          .to.deep.equal([section("t1", 1, "", 1), section("t2", 1, "", 1)]);
      });
      it("should extract code|code", function () {
        expect(this.part('t1.html', "
\n\t
foo
\n
"))
          .to.deep.equal([section("", 1, "
\n\t
foo
\n
", 1)]);
      });
      it("should extract comment|code|comment", function () {
        expect(this.part('t1.html', "\n"))
          .to.deep.equal([section("t1", 1, "\n", 2), section("t2", 2, "", 2)]);
      });
      it("should extract comment|code|comment|code", function () {
        expect(this.part('t1.html', "
\n\n
\n"))
          .to.deep.equal([section("t1", 1, "
\n", 1), section("t2", 2, "\n
\n", 3)]);
      });
      it("should skip directives", function () {
        expect(this.part('t.html', "
\n
"))
          .to.deep.equal([section("", 1, "
\n
", 1)]);
      });
      it("should explicitly skip directives", function () {
        expect(this.part('t.html', "
\n
", {noSkipDirectives: false}))
          .to.deep.equal([section("", 1, "
\n
", 1)]);
      });
      it("should not skip directives", function () {
        expect(this.part('t.html', "
\n
", {noSkipDirectives: true}))
          .to.deep.equal([section("", 1, "
\n", 1), section("[if foo]", 2, "
", 2)]);
      });
      it("should respect new extension", function () {
        expect(this.part('t1.foo', "\n", {extension: '.html'}))
          .to.deep.equal([section("t1", 1, "\n", 2)]);
      });
    });
  });
})();
<|endoftext|>