batman-rails-flo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +29 -0
  3. data/Rakefile +2 -0
  4. data/lib/batman-rails-flo.rb +5 -0
  5. data/lib/batman_rails_flo/railtie.rb +9 -0
  6. data/lib/batman_rails_flo/tasks.rake +14 -0
  7. data/lib/batman_rails_flo/version.rb +3 -0
  8. data/vendor/assets/javascripts/batman_rails_flo/flo_server.js +67 -0
  9. data/vendor/assets/javascripts/batman_rails_flo/live_reload.js.coffee +129 -0
  10. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/CNAME +1 -0
  11. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/CONTRIBUTING.md +9 -0
  12. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/LICENSE +22 -0
  13. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/README +50 -0
  14. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/bin/cake +7 -0
  15. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/bin/coffee +7 -0
  16. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/browser.js +134 -0
  17. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/cake.js +112 -0
  18. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/coffee-script.js +335 -0
  19. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/command.js +569 -0
  20. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/grammar.js +631 -0
  21. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/helpers.js +252 -0
  22. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/index.js +11 -0
  23. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/lexer.js +926 -0
  24. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/nodes.js +3158 -0
  25. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/optparse.js +139 -0
  26. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/parser.js +724 -0
  27. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/register.js +66 -0
  28. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/repl.js +163 -0
  29. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/rewriter.js +475 -0
  30. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/scope.js +146 -0
  31. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/lib/coffee-script/sourcemap.js +161 -0
  32. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/LICENSE +21 -0
  33. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/examples/pow.js +6 -0
  34. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/index.js +82 -0
  35. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/package.json +34 -0
  36. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/readme.markdown +63 -0
  37. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/chmod.js +38 -0
  38. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/clobber.js +37 -0
  39. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/mkdirp.js +28 -0
  40. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/perm.js +32 -0
  41. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/perm_sync.js +39 -0
  42. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/race.js +41 -0
  43. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/rel.js +32 -0
  44. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/return.js +25 -0
  45. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/return_sync.js +24 -0
  46. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/root.js +18 -0
  47. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/sync.js +32 -0
  48. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/umask.js +28 -0
  49. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/node_modules/mkdirp/test/umask_sync.js +32 -0
  50. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/package.json +50 -0
  51. data/vendor/assets/javascripts/batman_rails_flo/node_modules/coffee-script/register.js +1 -0
  52. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/LICENSE +30 -0
  53. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/PATENTS +23 -0
  54. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/README.md +124 -0
  55. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/bin/flo +26 -0
  56. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/configure/configure.html +57 -0
  57. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/configure/configure.js +205 -0
  58. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/configure/style.css +334 -0
  59. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/connection.js +235 -0
  60. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/devtools.html +12 -0
  61. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/index.js +323 -0
  62. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/logger.js +42 -0
  63. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/logo.png +0 -0
  64. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/manifest.json +13 -0
  65. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/client/session.js +305 -0
  66. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/index.js +10 -0
  67. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/lib/flo.js +226 -0
  68. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/lib/server.js +94 -0
  69. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/README.md +66 -0
  70. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/index.js +437 -0
  71. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/LICENSE +23 -0
  72. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/README.md +218 -0
  73. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/minimatch.js +1055 -0
  74. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS +14 -0
  75. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/LICENSE +23 -0
  76. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/README.md +97 -0
  77. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js +252 -0
  78. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/package.json +33 -0
  79. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/test/basic.js +369 -0
  80. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/test/foreach.js +52 -0
  81. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js +50 -0
  82. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/LICENSE +27 -0
  83. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/README.md +53 -0
  84. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/bench.js +283 -0
  85. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/package.json +42 -0
  86. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/sigmund.js +39 -0
  87. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/node_modules/sigmund/test/basic.js +24 -0
  88. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/package.json +40 -0
  89. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/basic.js +399 -0
  90. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/brace-expand.js +33 -0
  91. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/caching.js +14 -0
  92. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/defaults.js +274 -0
  93. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/minimatch/test/extglob-ending-with-state-char.js +8 -0
  94. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/lib/walker.js +111 -0
  95. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/license +13 -0
  96. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/lib/makeerror.js +87 -0
  97. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/node_modules/tmpl/lib/tmpl.js +17 -0
  98. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/node_modules/tmpl/package.json +31 -0
  99. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/node_modules/tmpl/readme.md +10 -0
  100. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/package.json +34 -0
  101. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/node_modules/makeerror/readme.md +77 -0
  102. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/package.json +36 -0
  103. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/walker/readme.md +52 -0
  104. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/LICENSE +55 -0
  105. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/main.js +128 -0
  106. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/package.json +34 -0
  107. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/readme.mkd +72 -0
  108. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/d/d/t +0 -0
  109. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/d/t +0 -0
  110. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/test_monitor.js +31 -0
  111. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/test_monitorRootDirectory.js +28 -0
  112. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/node_modules/watch/test/test_watchTree.js +20 -0
  113. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/package.json +45 -0
  114. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/sane/test/test.js +243 -0
  115. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/CHANGELOG.md +81 -0
  116. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/LICENSE +177 -0
  117. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/Makefile +11 -0
  118. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/README.md +245 -0
  119. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/binding.gyp +14 -0
  120. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Makefile +355 -0
  121. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/linker.lock +0 -0
  122. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/obj.target/validation/src/validation.o +0 -0
  123. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/obj.target/xor/src/xor.o +0 -0
  124. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/validation.node +0 -0
  125. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/Release/xor.node +0 -0
  126. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/binding.Makefile +6 -0
  127. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/config.gypi +115 -0
  128. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/gyp-mac-tool +512 -0
  129. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/validation.target.mk +154 -0
  130. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/build/xor.target.mk +154 -0
  131. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/index.js +1 -0
  132. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/install.js +31 -0
  133. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/Constants.js +23 -0
  134. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/Deprecation.js +38 -0
  135. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/Validation.fallback.js +12 -0
  136. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/Validation.js +18 -0
  137. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketClient.js +359 -0
  138. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketConnection.js +717 -0
  139. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketFrame.js +282 -0
  140. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketRequest.js +478 -0
  141. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketRouter.js +154 -0
  142. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketRouterRequest.js +59 -0
  143. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/WebSocketServer.js +216 -0
  144. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/utils.js +7 -0
  145. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/websocket.js +11 -0
  146. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/xor.fallback.js +13 -0
  147. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/lib/xor.js +18 -0
  148. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/package.json +43 -0
  149. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/src/validation.cc +144 -0
  150. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/src/xor.cpp +86 -0
  151. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/vendor/FastBufferList.js +192 -0
  152. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/vendor/node-ctype/LICENSE +18 -0
  153. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/node_modules/websocket/vendor/node-ctype/ctio-faster.js +1126 -0
  154. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/package.json +25 -0
  155. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/client/browser_websocket.js +63 -0
  156. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/client/connection_test.js +57 -0
  157. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/client/logger_mock.js +15 -0
  158. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/client/session_test.js +194 -0
  159. data/vendor/assets/javascripts/batman_rails_flo/node_modules/fb-flo/test/server/flo_test.js +211 -0
  160. data/vendor/assets/javascripts/batman_rails_flo/package.json +15 -0
  161. data/vendor/assets/javascripts/batman_rails_flo/reload_event_handler.js.coffee +56 -0
  162. metadata +232 -0
@@ -0,0 +1,18 @@
1
+ Copyright 2011, Robert Mustacchi. All rights reserved.
2
+ Permission is hereby granted, free of charge, to any person obtaining a copy
3
+ of this software and associated documentation files (the "Software"), to
4
+ deal in the Software without restriction, including without limitation the
5
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
6
+ sell copies of the Software, and to permit persons to whom the Software is
7
+ furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in
10
+ all copies or substantial portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
15
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
17
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
18
+ IN THE SOFTWARE.
@@ -0,0 +1,1126 @@
1
+ /*
2
+ * rm - Feb 2011
3
+ * ctio-faster.js:
4
+ * This file is a modification of ctio.js that removes all the runtime sanity
5
+ * checking for efficiency.
6
+ *
7
+ * A simple way to read and write simple ctypes. Of course, as you'll find the
8
+ * code isn't as simple as it might appear. The following types are currently
9
+ * supported in big and little endian formats:
10
+ *
11
+ * uint8_t int8_t
12
+ * uint16_t int16_t
13
+ * uint32_t int32_t
14
+ * float (single precision IEEE 754)
15
+ * double (double precision IEEE 754)
16
+ *
17
+ * This is designed to work in Node and v8. It may in fact work in other
18
+ * Javascript interpreters (that'd be pretty neat), but it hasn't been tested.
19
+ * If you find that it does in fact work, that's pretty cool. Try and pass word
20
+ * back to the original author.
21
+ *
22
+ * Note to the reader: If you're tabstop isn't set to 8, parts of this may look
23
+ * weird.
24
+ */
25
+
26
+ /*
27
+ * Numbers in Javascript have a secret: all numbers must be represented with an
28
+ * IEEE-754 double. The double has a mantissa with a length of 52 bits with an
29
+ * implicit one. Thus the range of integers that can be represented is limited
30
+ * to the size of the mantissa, this makes reading and writing 64-bit integers
31
+ * difficult, but far from impossible.
32
+ *
33
+ * Another side effect of this representation is what happens when you use the
34
+ * bitwise operators, i.e. shift left, shift right, and, or, etc. In Javascript,
35
+ * each operand and the result is cast to a signed 32-bit number. However, in
36
+ * the case of >>> the values are cast to an unsigned number.
37
+ */
38
+
39
+ /*
40
+ * A reminder on endian related issues:
41
+ *
42
+ * Big Endian: MSB -> First byte
43
+ * Little Endian: MSB->Last byte
44
+ */
45
+
46
+ /*
47
+ * An 8 bit unsigned integer involves doing no significant work.
48
+ */
49
+ function ruint8(buffer, endian, offset)
50
+ {
51
+ return (buffer[offset]);
52
+ }
53
+
54
+ /*
55
+ * For 16 bit unsigned numbers we can do all the casting that we want to do.
56
+ */
57
+ function ruint16(buffer, endian, offset)
58
+ {
59
+ var val = 0;
60
+ if (endian == 'big') {
61
+ val = buffer[offset] << 8;
62
+ val |= buffer[offset+1];
63
+ } else {
64
+ val = buffer[offset];
65
+ val |= buffer[offset+1] << 8;
66
+ }
67
+
68
+ return (val);
69
+ }
70
+
71
+ /*
72
+ * Because most bitshifting is done using signed numbers, if we would go into
73
+ * the realm where we use that 32nd bit, we'll end up going into the negative
74
+ * range. i.e.:
75
+ * > 200 << 24
76
+ * -939524096
77
+ *
78
+ * Not the value you'd expect. To work around this, we instead do a
79
+ * multiplication by (1 << 24) which does the same thing, but in a way that
80
+ * ensures we don't lose that bit.
81
+ */
82
+
83
+ /*
84
+ * Handle the case of losing our MSBit
85
+ */
86
+ function fixu32(upper, lower)
87
+ {
88
+ return ((upper * (1 << 24)) + lower);
89
+ }
90
+
91
+ function ruint32(buffer, endian, offset)
92
+ {
93
+ var val = 0;
94
+
95
+ if (endian == 'big') {
96
+ val = buffer[offset+1] << 16;
97
+ val |= buffer[offset+2] << 8;
98
+ val |= buffer[offset+3];
99
+ val = fixu32(buffer[offset], val);
100
+ } else {
101
+ val = buffer[offset+2] << 16;
102
+ val |= buffer[offset+1] << 8;
103
+ val |= buffer[offset];
104
+ val = fixu32(buffer[offset+3], val);
105
+ }
106
+
107
+ return (val);
108
+ }
109
+
110
+ /*
111
+ * Reads a 64-bit unsigned number. The astue observer will note that this
112
+ * doesn't quite work. Javascript has chosen to only have numbers that can be
113
+ * represented by a double. A double only has 52 bits of mantissa with an
114
+ * implicit 1, thus we have up to 53 bits to represent an integer. However, 2^53
115
+ * doesn't quite give us what we want. Isn't 53 bits enough for anyone? What
116
+ * could you have possibly wanted to represent that was larger than that? Oh,
117
+ * maybe a size? You mean we bypassed the 4 GB limit on file sizes, when did
118
+ * that happen?
119
+ *
120
+ * To get around this egregious language issue, we're going to instead construct
121
+ * an array of two 32 bit unsigned integers. Where arr[0] << 32 + arr[1] would
122
+ * give the actual number. However, note that the above code probably won't
123
+ * produce the desired results because of the way Javascript numbers are
124
+ * doubles.
125
+ */
126
+ function ruint64(buffer, endian, offset)
127
+ {
128
+ var val = new Array(2);
129
+
130
+ if (endian == 'big') {
131
+ val[0] = ruint32(buffer, endian, offset);
132
+ val[1] = ruint32(buffer, endian, offset+4);
133
+ } else {
134
+ val[0] = ruint32(buffer, endian, offset+4);
135
+ val[1] = ruint32(buffer, endian, offset);
136
+ }
137
+
138
+ return (val);
139
+ }
140
+
141
+
142
+ /*
143
+ * Signed integer types, yay team! A reminder on how two's complement actually
144
+ * works. The first bit is the signed bit, i.e. tells us whether or not the
145
+ * number should be positive or negative. If the two's complement value is
146
+ * positive, then we're done, as it's equivalent to the unsigned representation.
147
+ *
148
+ * Now if the number is positive, you're pretty much done, you can just leverage
149
+ * the unsigned translations and return those. Unfortunately, negative numbers
150
+ * aren't quite that straightforward.
151
+ *
152
+ * At first glance, one might be inclined to use the traditional formula to
153
+ * translate binary numbers between the positive and negative values in two's
154
+ * complement. (Though it doesn't quite work for the most negative value)
155
+ * Mainly:
156
+ * - invert all the bits
157
+ * - add one to the result
158
+ *
159
+ * Of course, this doesn't quite work in Javascript. Take for example the value
160
+ * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
161
+ * course, Javascript will do the following:
162
+ *
163
+ * > ~0xff80
164
+ * -65409
165
+ *
166
+ * Whoh there, Javascript, that's not quite right. But wait, according to
167
+ * Javascript that's perfectly correct. When Javascript ends up seeing the
168
+ * constant 0xff80, it has no notion that it is actually a signed number. It
169
+ * assumes that we've input the unsigned value 0xff80. Thus, when it does the
170
+ * binary negation, it casts it into a signed value, (positive 0xff80). Then
171
+ * when you perform binary negation on that, it turns it into a negative number.
172
+ *
173
+ * Instead, we're going to have to use the following general formula, that works
174
+ * in a rather Javascript friendly way. I'm glad we don't support this kind of
175
+ * weird numbering scheme in the kernel.
176
+ *
177
+ * (BIT-MAX - (unsigned)val + 1) * -1
178
+ *
179
+ * The astute observer, may think that this doesn't make sense for 8-bit numbers
180
+ * (really it isn't necessary for them). However, when you get 16-bit numbers,
181
+ * you do. Let's go back to our prior example and see how this will look:
182
+ *
183
+ * (0xffff - 0xff80 + 1) * -1
184
+ * (0x007f + 1) * -1
185
+ * (0x0080) * -1
186
+ *
187
+ * Doing it this way ends up allowing us to treat it appropriately in
188
+ * Javascript. Sigh, that's really quite ugly for what should just be a few bit
189
+ * shifts, ~ and &.
190
+ */
191
+
192
+ /*
193
+ * Endianness doesn't matter for 8-bit signed values. We could in fact optimize
194
+ * this case because the more traditional methods work, but for consistency,
195
+ * we'll keep doing this the same way.
196
+ */
197
+ function rsint8(buffer, endian, offset)
198
+ {
199
+ var neg;
200
+
201
+ neg = buffer[offset] & 0x80;
202
+ if (!neg)
203
+ return (buffer[offset]);
204
+
205
+ return ((0xff - buffer[offset] + 1) * -1);
206
+ }
207
+
208
+ /*
209
+ * The 16-bit version requires a bit more effort. In this case, we can leverage
210
+ * our unsigned code to generate the value we want to return.
211
+ */
212
+ function rsint16(buffer, endian, offset)
213
+ {
214
+ var neg, val;
215
+
216
+ val = ruint16(buffer, endian, offset);
217
+ neg = val & 0x8000;
218
+ if (!neg)
219
+ return (val);
220
+
221
+ return ((0xffff - val + 1) * -1);
222
+ }
223
+
224
+ /*
225
+ * We really shouldn't leverage our 32-bit code here and instead utilize the
226
+ * fact that we know that since these are signed numbers, we can do all the
227
+ * shifting and binary anding to generate the 32-bit number. But, for
228
+ * consistency we'll do the same. If we want to do otherwise, we should instead
229
+ * make the 32 bit unsigned code do the optimization. But as long as there
230
+ * aren't floats secretly under the hood for that, we /should/ be okay.
231
+ */
232
+ function rsint32(buffer, endian, offset)
233
+ {
234
+ var neg, val;
235
+
236
+ val = ruint32(buffer, endian, offset);
237
+ neg = val & 0x80000000;
238
+ if (!neg)
239
+ return (val);
240
+
241
+ return ((0xffffffff - val + 1) * -1);
242
+ }
243
+
244
+ /*
245
+ * The signed version of this code suffers from all of the same problems of the
246
+ * other 64 bit version.
247
+ */
248
+ function rsint64(buffer, endian, offset)
249
+ {
250
+ var neg, val;
251
+
252
+ val = ruint64(buffer, endian, offset);
253
+ neg = val[0] & 0x80000000;
254
+
255
+ if (!neg)
256
+ return (val);
257
+
258
+ val[0] = (0xffffffff - val[0]) * -1;
259
+ val[1] = (0xffffffff - val[1] + 1) * -1;
260
+
261
+ return (val);
262
+ }
263
+
264
+ /*
265
+ * We now move onto IEEE 754: The traditional form for floating point numbers
266
+ * and what is secretly hiding at the heart of everything in this. I really hope
267
+ * that someone is actually using this, as otherwise, this effort is probably
268
+ * going to be more wasted.
269
+ *
270
+ * One might be tempted to use parseFloat here, but that wouldn't work at all
271
+ * for several reasons. Mostly due to the way floats actually work, and
272
+ * parseFloat only actually works in base 10. I don't see base 10 anywhere near
273
+ * this file.
274
+ *
275
+ * In this case we'll implement the single and double precision versions. The
276
+ * quadruple precision, while probably useful, wouldn't really be accepted by
277
+ * Javascript, so let's not even waste our time.
278
+ *
279
+ * So let's review how this format looks like. A single precision value is 32
280
+ * bits and has three parts:
281
+ * - Sign bit
282
+ * - Exponent (Using bias notation)
283
+ * - Mantissa
284
+ *
285
+ * |s|eeeeeeee|mmmmmmmmmmmmmmmmmmmmmmmmm|
286
+ * 31| 30-23 | 22 - 0 |
287
+ *
288
+ * The exponent is stored in a biased input. The bias in this case 127.
289
+ * Therefore, our exponent is equal to the 8-bit value - 127.
290
+ *
291
+ * By default, a number is normalized in IEEE, that means that the mantissa has
292
+ * an implicit one that we don't see. So really the value stored is 1.m.
293
+ * However, if the exponent is all zeros, then instead we have to shift
294
+ * everything to the right one and there is no more implicit one.
295
+ *
296
+ * Special values:
297
+ * - Positive Infinity:
298
+ * Sign: 0
299
+ * Exponent: All 1s
300
+ * Mantissa: 0
301
+ * - Negative Infinity:
302
+ * Sign: 1
303
+ * Exponent: All 1s
304
+ * Mantissa: 0
305
+ * - NaN:
306
+ * Sign: *
307
+ * Exponent: All 1s
308
+ * Mantissa: non-zero
309
+ * - Zero:
310
+ * Sign: *
311
+ * Exponent: All 0s
312
+ * Mantissa: 0
313
+ *
314
+ * In the case of zero, the sign bit determines whether we get a positive or
315
+ * negative zero. However, since Javascript cannot determine the difference
316
+ * between the two: i.e. -0 == 0, we just always return 0.
317
+ *
318
+ */
319
+ function rfloat(buffer, endian, offset)
320
+ {
321
+ var bytes = [];
322
+ var sign, exponent, mantissa, val;
323
+ var bias = 127;
324
+ var maxexp = 0xff;
325
+
326
+ /* Normalize the bytes to be in endian order */
327
+ if (endian == 'big') {
328
+ bytes[0] = buffer[offset];
329
+ bytes[1] = buffer[offset+1];
330
+ bytes[2] = buffer[offset+2];
331
+ bytes[3] = buffer[offset+3];
332
+ } else {
333
+ bytes[3] = buffer[offset];
334
+ bytes[2] = buffer[offset+1];
335
+ bytes[1] = buffer[offset+2];
336
+ bytes[0] = buffer[offset+3];
337
+ }
338
+
339
+ sign = bytes[0] & 0x80;
340
+ exponent = (bytes[0] & 0x7f) << 1;
341
+ exponent |= (bytes[1] & 0x80) >>> 7;
342
+ mantissa = (bytes[1] & 0x7f) << 16;
343
+ mantissa |= bytes[2] << 8;
344
+ mantissa |= bytes[3];
345
+
346
+ /* Check for special cases before we do general parsing */
347
+ if (!sign && exponent == maxexp && mantissa === 0)
348
+ return (Number.POSITIVE_INFINITY);
349
+
350
+ if (sign && exponent == maxexp && mantissa === 0)
351
+ return (Number.NEGATIVE_INFINITY);
352
+
353
+ if (exponent == maxexp && mantissa !== 0)
354
+ return (Number.NaN);
355
+
356
+ /*
357
+ * Javascript really doesn't have support for positive or negative zero.
358
+ * So we're not going to try and give it to you. That would be just
359
+ * plain weird. Besides -0 == 0.
360
+ */
361
+ if (exponent === 0 && mantissa === 0)
362
+ return (0);
363
+
364
+ /*
365
+ * Now we can deal with the bias and the determine whether the mantissa
366
+ * has the implicit one or not.
367
+ */
368
+ exponent -= bias;
369
+ if (exponent == -bias) {
370
+ exponent++;
371
+ val = 0;
372
+ } else {
373
+ val = 1;
374
+ }
375
+
376
+ val = (val + mantissa * Math.pow(2, -23)) * Math.pow(2, exponent);
377
+
378
+ if (sign)
379
+ val *= -1;
380
+
381
+ return (val);
382
+ }
383
+
384
+ /*
385
+ * Doubles in IEEE 754 are like their brothers except for a few changes and
386
+ * increases in size:
387
+ * - The exponent is now 11 bits
388
+ * - The mantissa is now 52 bits
389
+ * - The bias is now 1023
390
+ *
391
+ * |s|eeeeeeeeeee|mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm|
392
+ * 63| 62 - 52 | 51 - 0 |
393
+ * 63| 62 - 52 | 51 - 0 |
394
+ *
395
+ * While the size has increased a fair amount, we're going to end up keeping the
396
+ * same general formula for calculating the final value. As a reminder, this
397
+ * formula is:
398
+ *
399
+ * (-1)^s * (n + m) * 2^(e-b)
400
+ *
401
+ * Where:
402
+ * s is the sign bit
403
+ * n is (exponent > 0) ? 1 : 0 -- Determines whether we're normalized
404
+ * or not
405
+ * m is the mantissa
406
+ * e is the exponent specified
407
+ * b is the bias for the exponent
408
+ *
409
+ */
410
+ function rdouble(buffer, endian, offset)
411
+ {
412
+ var bytes = [];
413
+ var sign, exponent, mantissa, val, lowmant;
414
+ var bias = 1023;
415
+ var maxexp = 0x7ff;
416
+
417
+ /* Normalize the bytes to be in endian order */
418
+ if (endian == 'big') {
419
+ bytes[0] = buffer[offset];
420
+ bytes[1] = buffer[offset+1];
421
+ bytes[2] = buffer[offset+2];
422
+ bytes[3] = buffer[offset+3];
423
+ bytes[4] = buffer[offset+4];
424
+ bytes[5] = buffer[offset+5];
425
+ bytes[6] = buffer[offset+6];
426
+ bytes[7] = buffer[offset+7];
427
+ } else {
428
+ bytes[7] = buffer[offset];
429
+ bytes[6] = buffer[offset+1];
430
+ bytes[5] = buffer[offset+2];
431
+ bytes[4] = buffer[offset+3];
432
+ bytes[3] = buffer[offset+4];
433
+ bytes[2] = buffer[offset+5];
434
+ bytes[1] = buffer[offset+6];
435
+ bytes[0] = buffer[offset+7];
436
+ }
437
+
438
+ /*
439
+ * We can construct the exponent and mantissa the same way as we did in
440
+ * the case of a float, just increase the range of the exponent.
441
+ */
442
+ sign = bytes[0] & 0x80;
443
+ exponent = (bytes[0] & 0x7f) << 4;
444
+ exponent |= (bytes[1] & 0xf0) >>> 4;
445
+
446
+ /*
447
+ * This is going to be ugly but then again, we're dealing with IEEE 754.
448
+ * This could probably be done as a node add on in a few lines of C++,
449
+ * but oh we'll, we've made it this far so let's be native the rest of
450
+ * the way...
451
+ *
452
+ * What we're going to do is break the mantissa into two parts, the
453
+ * lower 24 bits and the upper 28 bits. We'll multiply the upper 28 bits
454
+ * by the appropriate power and then add in the lower 24-bits. Not
455
+ * really that great. It's pretty much a giant kludge to deal with
456
+ * Javascript eccentricities around numbers.
457
+ */
458
+ lowmant = bytes[7];
459
+ lowmant |= bytes[6] << 8;
460
+ lowmant |= bytes[5] << 16;
461
+ mantissa = bytes[4];
462
+ mantissa |= bytes[3] << 8;
463
+ mantissa |= bytes[2] << 16;
464
+ mantissa |= (bytes[1] & 0x0f) << 24;
465
+ mantissa *= Math.pow(2, 24); /* Equivalent to << 24, but JS compat */
466
+ mantissa += lowmant;
467
+
468
+ /* Check for special cases before we do general parsing */
469
+ if (!sign && exponent == maxexp && mantissa === 0)
470
+ return (Number.POSITIVE_INFINITY);
471
+
472
+ if (sign && exponent == maxexp && mantissa === 0)
473
+ return (Number.NEGATIVE_INFINITY);
474
+
475
+ if (exponent == maxexp && mantissa !== 0)
476
+ return (Number.NaN);
477
+
478
+ /*
479
+ * Javascript really doesn't have support for positive or negative zero.
480
+ * So we're not going to try and give it to you. That would be just
481
+ * plain weird. Besides -0 == 0.
482
+ */
483
+ if (exponent === 0 && mantissa === 0)
484
+ return (0);
485
+
486
+ /*
487
+ * Now we can deal with the bias and the determine whether the mantissa
488
+ * has the implicit one or not.
489
+ */
490
+ exponent -= bias;
491
+ if (exponent == -bias) {
492
+ exponent++;
493
+ val = 0;
494
+ } else {
495
+ val = 1;
496
+ }
497
+
498
+ val = (val + mantissa * Math.pow(2, -52)) * Math.pow(2, exponent);
499
+
500
+ if (sign)
501
+ val *= -1;
502
+
503
+ return (val);
504
+ }
505
+
506
+ /*
507
+ * Now that we have gone through the pain of reading the individual types, we're
508
+ * probably going to want some way to write these back. None of this is going to
509
+ * be good. But since we have Javascript numbers this should certainly be more
510
+ * interesting. Though we can constrain this end a little bit more in what is
511
+ * valid. For now, let's go back to our friends the unsigned value.
512
+ */
513
+
514
+ /*
515
+ * Unsigned numbers seem deceptively easy. Here are the general steps and rules
516
+ * that we are going to take:
517
+ * - If the number is negative, throw an Error
518
+ * - Truncate any floating point portion
519
+ * - Take the modulus of the number in our base
520
+ * - Write it out to the buffer in the endian format requested at the offset
521
+ */
522
+
523
+ /*
524
+ * We have to make sure that the value is a valid integer. This means that it is
525
+ * non-negative. It has no fractional component and that it does not exceed the
526
+ * maximum allowed value.
527
+ *
528
+ * value The number to check for validity
529
+ *
530
+ * max The maximum value
531
+ */
532
+ function prepuint(value, max)
533
+ {
534
+ if (typeof (value) != 'number')
535
+ throw (new (Error('cannot write a non-number as a number')));
536
+
537
+ if (value < 0)
538
+ throw (new Error('specified a negative value for writing an ' +
539
+ 'unsigned value'));
540
+
541
+ if (value > max)
542
+ throw (new Error('value is larger than maximum value for ' +
543
+ 'type'));
544
+
545
+ if (Math.floor(value) !== value)
546
+ throw (new Error('value has a fractional component'));
547
+
548
+ return (value);
549
+ }
550
+
551
+ /*
552
+ * 8-bit version, classy. We can ignore endianness which is good.
553
+ */
554
+ function wuint8(value, endian, buffer, offset)
555
+ {
556
+ var val;
557
+
558
+ val = prepuint(value, 0xff);
559
+ buffer[offset] = val;
560
+ }
561
+
562
+ /*
563
+ * Pretty much the same as the 8-bit version, just this time we need to worry
564
+ * about endian related issues.
565
+ */
566
+ function wuint16(value, endian, buffer, offset)
567
+ {
568
+ var val;
569
+
570
+ val = prepuint(value, 0xffff);
571
+ if (endian == 'big') {
572
+ buffer[offset] = (val & 0xff00) >>> 8;
573
+ buffer[offset+1] = val & 0x00ff;
574
+ } else {
575
+ buffer[offset+1] = (val & 0xff00) >>> 8;
576
+ buffer[offset] = val & 0x00ff;
577
+ }
578
+ }
579
+
580
+ /*
581
+ * The 32-bit version is going to have to be a little different unfortunately.
582
+ * We can't quite bitshift to get the largest byte, because that would end up
583
+ * getting us caught by the signed values.
584
+ *
585
+ * And yes, we do want to subtract out the lower part by default. This means
586
+ * that when we do the division, it will be treated as a bit shift and we won't
587
+ * end up generating a floating point value. If we did generate a floating point
588
+ * value we'd have to truncate it intelligently, this saves us that problem and
589
+ * may even be somewhat faster under the hood.
590
+ */
591
+ function wuint32(value, endian, buffer, offset)
592
+ {
593
+ var val;
594
+
595
+ val = prepuint(value, 0xffffffff);
596
+ if (endian == 'big') {
597
+ buffer[offset] = (val - (val & 0x00ffffff)) / Math.pow(2, 24);
598
+ buffer[offset+1] = (val >>> 16) & 0xff;
599
+ buffer[offset+2] = (val >>> 8) & 0xff;
600
+ buffer[offset+3] = val & 0xff;
601
+ } else {
602
+ buffer[offset+3] = (val - (val & 0x00ffffff)) /
603
+ Math.pow(2, 24);
604
+ buffer[offset+2] = (val >>> 16) & 0xff;
605
+ buffer[offset+1] = (val >>> 8) & 0xff;
606
+ buffer[offset] = val & 0xff;
607
+ }
608
+ }
609
+
610
+ /*
611
+ * Unlike the other versions, we expect the value to be in the form of two
612
+ * arrays where value[0] << 32 + value[1] would result in the value that we
613
+ * want.
614
+ */
615
+ function wuint64(value, endian, buffer, offset)
616
+ {
617
+ prepuint(value[0], 0xffffffff);
618
+ prepuint(value[1], 0xffffffff);
619
+
620
+ if (endian == 'big') {
621
+ wuint32(value[0], endian, buffer, offset);
622
+ wuint32(value[1], endian, buffer, offset+4);
623
+ } else {
624
+ wuint32(value[0], endian, buffer, offset+4);
625
+ wuint32(value[1], endian, buffer, offset);
626
+ }
627
+ }
628
+
629
+ /*
630
+ * We now move onto our friends in the signed number category. Unlike unsigned
631
+ * numbers, we're going to have to worry a bit more about how we put values into
632
+ * arrays. Since we are only worrying about signed 32-bit values, we're in
633
+ * slightly better shape. Unfortunately, we really can't do our favorite binary
634
+ * & in this system. It really seems to do the wrong thing. For example:
635
+ *
636
+ * > -32 & 0xff
637
+ * 224
638
+ *
639
+ * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
640
+ * this aren't treated as a signed number. Ultimately a bad thing.
641
+ *
642
+ * What we're going to want to do is basically create the unsigned equivalent of
643
+ * our representation and pass that off to the wuint* functions. To do that
644
+ * we're going to do the following:
645
+ *
646
+ * - if the value is positive
647
+ * we can pass it directly off to the equivalent wuint
648
+ * - if the value is negative
649
+ * we do the following computation:
650
+ * mb + val + 1, where
651
+ * mb is the maximum unsigned value in that byte size
652
+ * val is the Javascript negative integer
653
+ *
654
+ *
655
+ * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
656
+ * you do out the computations:
657
+ *
658
+ * 0xffff - 128 + 1
659
+ * 0xffff - 127
660
+ * 0xff80
661
+ *
662
+ * You can then encode this value as the signed version. This is really rather
663
+ * hacky, but it should work and get the job done which is our goal here.
664
+ *
665
+ * Thus the overall flow is:
666
+ * - Truncate the floating point part of the number
667
+ * - We don't have to take the modulus, because the unsigned versions will
668
+ * take care of that for us. And we don't have to worry about that
669
+ * potentially causing bad things to happen because of sign extension
670
+ * - Pass it off to the appropriate unsigned version, potentially modifying
671
+ * the negative portions as necessary.
672
+ */
673
+
674
+ /*
675
+ * A series of checks to make sure we actually have a signed 32-bit number
676
+ */
677
+ function prepsint(value, max, min)
678
+ {
679
+ if (typeof (value) != 'number')
680
+ throw (new (Error('cannot write a non-number as a number')));
681
+
682
+ if (value > max)
683
+ throw (new Error('value larger than maximum allowed value'));
684
+
685
+ if (value < min)
686
+ throw (new Error('value smaller than minimum allowed value'));
687
+
688
+ if (Math.floor(value) !== value)
689
+ throw (new Error('value has a fractional component'));
690
+
691
+ return (value);
692
+ }
693
+
694
+ /*
695
+ * The 8-bit version of the signed value. Overall, fairly straightforward.
696
+ */
697
+ function wsint8(value, endian, buffer, offset)
698
+ {
699
+ var val;
700
+
701
+ val = prepsint(value, 0x7f, -0xf0);
702
+ if (val >= 0)
703
+ wuint8(val, endian, buffer, offset);
704
+ else
705
+ wuint8(0xff + val + 1, endian, buffer, offset);
706
+ }
707
+
708
+ /*
709
+ * The 16-bit version of the signed value. Also, fairly straightforward.
710
+ */
711
+ function wsint16(value, endian, buffer, offset)
712
+ {
713
+ var val;
714
+
715
+ val = prepsint(value, 0x7fff, -0xf000);
716
+ if (val >= 0)
717
+ wuint16(val, endian, buffer, offset);
718
+ else
719
+ wuint16(0xffff + val + 1, endian, buffer, offset);
720
+
721
+ }
722
+
723
+ /*
724
+ * We can do this relatively easily by leveraging the code used for 32-bit
725
+ * unsigned code.
726
+ */
727
+ function wsint32(value, endian, buffer, offset)
728
+ {
729
+ var val;
730
+
731
+ val = prepsint(value, 0x7fffffff, -0xf0000000);
732
+ if (val >= 0)
733
+ wuint32(val, endian, buffer, offset);
734
+ else
735
+ wuint32(0xffffffff + val + 1, endian, buffer, offset);
736
+ }
737
+
738
+ /*
739
+ * The signed 64 bit integer should by in the same format as when received.
740
+ * Mainly it should ensure that the value is an array of two integers where
741
+ * value[0] << 32 + value[1] is the desired number.
742
+ */
743
+ function wsint64(value, endian, buffer, offset)
744
+ {
745
+ var vals = new Array(2);
746
+
747
+ prepsint(value[0], 0x7fffffff, -0xf0000000);
748
+ prepsint(value[1], 0xffffffff, -0xffffffff);
749
+
750
+ /* Fix negative numbers */
751
+ if (value[0] < 0 || value[1] < 0) {
752
+ vals[0] = 0xffffffff - Math.abs(value[0]);
753
+ vals[1] = 0x100000000 - Math.abs(value[1]);
754
+ if (vals[1] == 0x100000000) {
755
+ vals[1] = 0;
756
+ vals[0]++;
757
+ }
758
+ } else {
759
+ vals[0] = value[0];
760
+ vals[1] = value[1];
761
+ }
762
+
763
+ if (endian == 'big') {
764
+ wuint32(vals[0], endian, buffer, offset);
765
+ wuint32(vals[1], endian, buffer, offset+4);
766
+ } else {
767
+ wuint32(vals[0], endian, buffer, offset+4);
768
+ wuint32(vals[1], endian, buffer, offset);
769
+ }
770
+ }
771
+
772
+ /*
773
+ * Now we are moving onto the weirder of these, the float and double. For this
774
+ * we're going to just have to do something that's pretty weird. First off, we
775
+ * have no way to get at the underlying float representation, at least not
776
+ * easily. But that doesn't mean we can't figure it out, we just have to use our
777
+ * heads.
778
+ *
779
+ * One might propose to use Number.toString(2). Of course, this is not really
780
+ * that good, because the ECMAScript 262 v3 Standard says the following Section
781
+ * 15.7.4.2-Number.prototype.toString (radix):
782
+ *
783
+ * If radix is an integer from 2 to 36, but not 10, the result is a string, the
784
+ * choice of which is implementation-dependent.
785
+ *
786
+ * Well that doesn't really help us one bit now does it? We could use the
787
+ * standard base 10 version of the string, but that's just going to create more
788
+ * errors as we end up trying to convert it back to a binary value. So, really
789
+ * this just means we have to be non-lazy and parse the structure intelligently.
790
+ *
791
+ * First off, we can do the basic checks: NaN, positive and negative infinity.
792
+ *
793
+ * Now that those are done we can work backwards to generate the mantissa and
794
+ * exponent.
795
+ *
796
+ * The first thing we need to do is determine the sign bit, easy to do, check
797
+ * whether the value is less than 0. And convert the number to its absolute
798
+ * value representation. Next, we need to determine if the value is less than
799
+ * one or greater than or equal to one and from there determine what power was
800
+ * used to get there. What follows is now specific to floats, though the general
801
+ * ideas behind this will hold for doubles as well, but the exact numbers
802
+ * involved will change.
803
+ *
804
+ * Once we have that power we can determine the exponent and the mantissa. Call
805
+ * the value that has the number of bits to reach the power ebits. In the
806
+ * general case they have the following values:
807
+ *
808
+ * exponent 127 + ebits
809
+ * mantissa value * 2^(23 - ebits) & 0x7fffff
810
+ *
811
+ * In the case where the value of ebits is <= -127 we are now in the case where
812
+ * we no longer have normalized numbers. In this case the values take on the
813
+ * following values:
814
+ *
815
+ * exponent 0
816
+ * mantissa value * 2^149 & 0x7fffff
817
+ *
818
+ * Once we have the values for the sign, mantissa, and exponent. We reconstruct
819
+ * the four bytes as follows:
820
+ *
821
+ * byte0 sign bit and seven most significant bits from the exp
822
+ * sign << 7 | (exponent & 0xfe) >>> 1
823
+ *
824
+ * byte1 lsb from the exponent and 7 top bits from the mantissa
825
+ * (exponent & 0x01) << 7 | (mantissa & 0x7f0000) >>> 16
826
+ *
827
+ * byte2 bits 8-15 (zero indexing) from mantissa
828
+ * mantissa & 0xff00 >> 8
829
+ *
830
+ * byte3 bits 0-7 from mantissa
831
+ * mantissa & 0xff
832
+ *
833
+ * Once we have this we have to assign them into the buffer in proper endian
834
+ * order.
835
+ */
836
+
837
+ /*
838
+ * Compute the log base 2 of the value. Now, someone who remembers basic
839
+ * properties of logarithms will point out that we could use the change of base
840
+ * formula for logs, and in fact that would be astute, because that's what we'll
841
+ * do for now. It feels cleaner, albeit it may be less efficient than just
842
+ * iterating and dividing by 2. We may want to come back and revisit that some
843
+ * day.
844
+ */
845
+ function log2(value)
846
+ {
847
+ return (Math.log(value) / Math.log(2));
848
+ }
849
+
850
+ /*
851
+ * Helper to determine the exponent of the number we're looking at.
852
+ */
853
+ function intexp(value)
854
+ {
855
+ return (Math.floor(log2(value)));
856
+ }
857
+
858
+ /*
859
+ * Helper to determine the exponent of the fractional part of the value.
860
+ */
861
+ function fracexp(value)
862
+ {
863
+ return (Math.floor(log2(value)));
864
+ }
865
+
866
+ function wfloat(value, endian, buffer, offset)
867
+ {
868
+ var sign, exponent, mantissa, ebits;
869
+ var bytes = [];
870
+
871
+ if (isNaN(value)) {
872
+ sign = 0;
873
+ exponent = 0xff;
874
+ mantissa = 23;
875
+ } else if (value == Number.POSITIVE_INFINITY) {
876
+ sign = 0;
877
+ exponent = 0xff;
878
+ mantissa = 0;
879
+ } else if (value == Number.NEGATIVE_INFINITY) {
880
+ sign = 1;
881
+ exponent = 0xff;
882
+ mantissa = 0;
883
+ } else {
884
+ /* Well we have some work to do */
885
+
886
+ /* Thankfully the sign bit is trivial */
887
+ if (value < 0) {
888
+ sign = 1;
889
+ value = Math.abs(value);
890
+ } else {
891
+ sign = 0;
892
+ }
893
+
894
+ /* Use the correct function to determine number of bits */
895
+ if (value < 1)
896
+ ebits = fracexp(value);
897
+ else
898
+ ebits = intexp(value);
899
+
900
+ /* Time to deal with the issues surrounding normalization */
901
+ if (ebits <= -127) {
902
+ exponent = 0;
903
+ mantissa = (value * Math.pow(2, 149)) & 0x7fffff;
904
+ } else {
905
+ exponent = 127 + ebits;
906
+ mantissa = value * Math.pow(2, 23 - ebits);
907
+ mantissa &= 0x7fffff;
908
+ }
909
+ }
910
+
911
+ bytes[0] = sign << 7 | (exponent & 0xfe) >>> 1;
912
+ bytes[1] = (exponent & 0x01) << 7 | (mantissa & 0x7f0000) >>> 16;
913
+ bytes[2] = (mantissa & 0x00ff00) >>> 8;
914
+ bytes[3] = mantissa & 0x0000ff;
915
+
916
+ if (endian == 'big') {
917
+ buffer[offset] = bytes[0];
918
+ buffer[offset+1] = bytes[1];
919
+ buffer[offset+2] = bytes[2];
920
+ buffer[offset+3] = bytes[3];
921
+ } else {
922
+ buffer[offset] = bytes[3];
923
+ buffer[offset+1] = bytes[2];
924
+ buffer[offset+2] = bytes[1];
925
+ buffer[offset+3] = bytes[0];
926
+ }
927
+ }
928
+
929
+ /*
930
+ * Now we move onto doubles. Doubles are similar to floats in pretty much all
931
+ * ways except that the processing isn't quite as straightforward because we
932
+ * can't always use shifting, i.e. we have > 32 bit values.
933
+ *
934
+ * We're going to proceed in an identical fashion to floats and utilize the same
935
+ * helper functions. All that really is changing are the specific values that we
936
+ * use to do the calculations. Thus, to review we have to do the following.
937
+ *
938
+ * First get the sign bit and convert the value to its absolute value
939
+ * representation. Next, we determine the number of bits that we used to get to
940
+ * the value, branching whether the value is greater than or less than 1. Once
941
+ * we have that value which we will again call ebits, we have to do the
942
+ * following in the general case:
943
+ *
944
+ * exponent 1023 + ebits
945
+ * mantissa [value * 2^(52 - ebits)] % 2^52
946
+ *
947
+ * In the case where the value of ebits <= -1023 we no longer use normalized
948
+ * numbers, thus like with floats we have to do slightly different processing:
949
+ *
950
+ * exponent 0
951
+ * mantissa [value * 2^1074] % 2^52
952
+ *
953
+ * Once we have determined the sign, exponent and mantissa we can construct the
954
+ * bytes as follows:
955
+ *
956
+ * byte0 sign bit and seven most significant bits form the exp
957
+ * sign << 7 | (exponent & 0x7f0) >>> 4
958
+ *
959
+ * byte1 Remaining 4 bits from the exponent and the four most
960
+ * significant bits from the mantissa 48-51
961
+ * (exponent & 0x00f) << 4 | mantissa >>> 48
962
+ *
963
+ * byte2 Bits 40-47 from the mantissa
964
+ * (mantissa >>> 40) & 0xff
965
+ *
966
+ * byte3 Bits 32-39 from the mantissa
967
+ * (mantissa >>> 32) & 0xff
968
+ *
969
+ * byte4 Bits 24-31 from the mantissa
970
+ * (mantissa >>> 24) & 0xff
971
+ *
972
+ * byte5 Bits 16-23 from the Mantissa
973
+ * (mantissa >>> 16) & 0xff
974
+ *
975
+ * byte6 Bits 8-15 from the mantissa
976
+ * (mantissa >>> 8) & 0xff
977
+ *
978
+ * byte7 Bits 0-7 from the mantissa
979
+ * mantissa & 0xff
980
+ *
981
+ * Now we can't quite do the right shifting that we want in bytes 1 - 3, because
982
+ * we'll have extended too far and we'll lose those values when we try and do
983
+ * the shift. Instead we have to use an alternate approach. To try and stay out
984
+ * of floating point, what we'll do is say that mantissa -= bytes[4-7] and then
985
+ * divide by 2^32. Once we've done that we can use binary arithmetic. Oof,
986
+ * that's ugly, but it seems to avoid using floating point (just based on how v8
987
+ * seems to be optimizing for base 2 arithmetic).
988
+ */
989
+ function wdouble(value, endian, buffer, offset)
990
+ {
991
+ var sign, exponent, mantissa, ebits;
992
+ var bytes = [];
993
+
994
+ if (isNaN(value)) {
995
+ sign = 0;
996
+ exponent = 0x7ff;
997
+ mantissa = 23;
998
+ } else if (value == Number.POSITIVE_INFINITY) {
999
+ sign = 0;
1000
+ exponent = 0x7ff;
1001
+ mantissa = 0;
1002
+ } else if (value == Number.NEGATIVE_INFINITY) {
1003
+ sign = 1;
1004
+ exponent = 0x7ff;
1005
+ mantissa = 0;
1006
+ } else {
1007
+ /* Well we have some work to do */
1008
+
1009
+ /* Thankfully the sign bit is trivial */
1010
+ if (value < 0) {
1011
+ sign = 1;
1012
+ value = Math.abs(value);
1013
+ } else {
1014
+ sign = 0;
1015
+ }
1016
+
1017
+ /* Use the correct function to determine number of bits */
1018
+ if (value < 1)
1019
+ ebits = fracexp(value);
1020
+ else
1021
+ ebits = intexp(value);
1022
+
1023
+ /*
1024
+ * This is a total hack to determine a denormalized value.
1025
+ * Unfortunately, we sometimes do not get a proper value for
1026
+ * ebits, i.e. we lose the values that would get rounded off.
1027
+ *
1028
+ *
1029
+ * The astute observer may wonder why we would be
1030
+ * multiplying by two Math.pows rather than just summing
1031
+ * them. Well, that's to get around a small bug in the
1032
+ * way v8 seems to implement the function. On occasion
1033
+ * doing:
1034
+ *
1035
+ * foo * Math.pow(2, 1023 + 51)
1036
+ *
1037
+ * Causes us to overflow to infinity, where as doing:
1038
+ *
1039
+ * foo * Math.pow(2, 1023) * Math.pow(2, 51)
1040
+ *
1041
+ * Does not cause us to overflow. Go figure.
1042
+ *
1043
+ */
1044
+ if (value <= 2.225073858507201e-308 || ebits <= -1023) {
1045
+ exponent = 0;
1046
+ mantissa = value * Math.pow(2, 1023) * Math.pow(2, 51);
1047
+ mantissa %= Math.pow(2, 52);
1048
+ } else {
1049
+ /*
1050
+ * We might have gotten fucked by our floating point
1051
+ * logarithm magic. This is rather crappy, but that's
1052
+ * our luck. If we just had a log base 2 or access to
1053
+ * the stupid underlying representation this would have
1054
+ * been much easier and we wouldn't have such stupid
1055
+ * kludges or hacks.
1056
+ */
1057
+ if (ebits > 1023)
1058
+ ebits = 1023;
1059
+ exponent = 1023 + ebits;
1060
+ mantissa = value * Math.pow(2, -ebits);
1061
+ mantissa *= Math.pow(2, 52);
1062
+ mantissa %= Math.pow(2, 52);
1063
+ }
1064
+ }
1065
+
1066
+ /* Fill the bytes in backwards to deal with the size issues */
1067
+ bytes[7] = mantissa & 0xff;
1068
+ bytes[6] = (mantissa >>> 8) & 0xff;
1069
+ bytes[5] = (mantissa >>> 16) & 0xff;
1070
+ mantissa = (mantissa - (mantissa & 0xffffff)) / Math.pow(2, 24);
1071
+ bytes[4] = mantissa & 0xff;
1072
+ bytes[3] = (mantissa >>> 8) & 0xff;
1073
+ bytes[2] = (mantissa >>> 16) & 0xff;
1074
+ bytes[1] = (exponent & 0x00f) << 4 | mantissa >>> 24;
1075
+ bytes[0] = (sign << 7) | (exponent & 0x7f0) >>> 4;
1076
+
1077
+ if (endian == 'big') {
1078
+ buffer[offset] = bytes[0];
1079
+ buffer[offset+1] = bytes[1];
1080
+ buffer[offset+2] = bytes[2];
1081
+ buffer[offset+3] = bytes[3];
1082
+ buffer[offset+4] = bytes[4];
1083
+ buffer[offset+5] = bytes[5];
1084
+ buffer[offset+6] = bytes[6];
1085
+ buffer[offset+7] = bytes[7];
1086
+ } else {
1087
+ buffer[offset+7] = bytes[0];
1088
+ buffer[offset+6] = bytes[1];
1089
+ buffer[offset+5] = bytes[2];
1090
+ buffer[offset+4] = bytes[3];
1091
+ buffer[offset+3] = bytes[4];
1092
+ buffer[offset+2] = bytes[5];
1093
+ buffer[offset+1] = bytes[6];
1094
+ buffer[offset] = bytes[7];
1095
+ }
1096
+ }
1097
+
1098
+ /*
1099
+ * Actually export our work above. One might argue that we shouldn't expose
1100
+ * these interfaces and just force people to use the higher level abstractions
1101
+ * around this work. However, unlike say other libraries we've come across, this
1102
+ * interface has several properties: it makes sense, it's simple, and it's
1103
+ * useful.
1104
+ */
1105
+ exports.ruint8 = ruint8;
1106
+ exports.ruint16 = ruint16;
1107
+ exports.ruint32 = ruint32;
1108
+ exports.ruint64 = ruint64;
1109
+ exports.wuint8 = wuint8;
1110
+ exports.wuint16 = wuint16;
1111
+ exports.wuint32 = wuint32;
1112
+ exports.wuint64 = wuint64;
1113
+
1114
+ exports.rsint8 = rsint8;
1115
+ exports.rsint16 = rsint16;
1116
+ exports.rsint32 = rsint32;
1117
+ exports.rsint64 = rsint64;
1118
+ exports.wsint8 = wsint8;
1119
+ exports.wsint16 = wsint16;
1120
+ exports.wsint32 = wsint32;
1121
+ exports.wsint64 = wsint64;
1122
+
1123
+ exports.rfloat = rfloat;
1124
+ exports.rdouble = rdouble;
1125
+ exports.wfloat = wfloat;
1126
+ exports.wdouble = wdouble;