Browse Source

Add love.data module.

- Moved love.math.compress / decompress / decode / encode / hash to love.data.
- Changed love.data.compress/decompress to take the format argument first instead of second.
- Added love.data.newDataView. Returns a read-only subsection of an existing Data object.
- Added love.data.newByteData. Mostly useful in combination with LuaJIT's FFI as it has no extra methods currently.
- Added implementations of Lua 5.3's data packing APIs: love.data.packString / packData / unpack / getPackedSize.

Resolves issue #1336.
Resolves issue #1331.

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
90e86c329d
50 changed files with 2182 additions and 545 deletions
  1. 42 18
      CMakeLists.txt
  2. 25 0
      license.txt
  3. 144 72
      platform/xcode/liblove.xcodeproj/project.pbxproj
  4. 2 1
      src/common/Module.h
  5. 2 1
      src/common/config.h
  6. 0 0
      src/libraries/lua53/lprefix.h
  7. 585 0
      src/libraries/lua53/lstrlib.c
  8. 30 0
      src/libraries/lua53/lstrlib.h
  9. 0 0
      src/libraries/lua53/lutf8lib.c
  10. 3 3
      src/libraries/lua53/lutf8lib.h
  11. 90 0
      src/modules/data/ByteData.cpp
  12. 58 0
      src/modules/data/ByteData.h
  13. 2 2
      src/modules/data/CompressedData.cpp
  14. 4 7
      src/modules/data/CompressedData.h
  15. 5 7
      src/modules/data/Compressor.cpp
  16. 3 6
      src/modules/data/Compressor.h
  17. 267 0
      src/modules/data/DataModule.cpp
  18. 124 0
      src/modules/data/DataModule.h
  19. 71 0
      src/modules/data/DataView.cpp
  20. 57 0
      src/modules/data/DataView.h
  21. 30 34
      src/modules/data/HashFunction.cpp
  22. 15 8
      src/modules/data/HashFunction.h
  23. 46 0
      src/modules/data/wrap_ByteData.cpp
  24. 36 0
      src/modules/data/wrap_ByteData.h
  25. 3 3
      src/modules/data/wrap_CompressedData.cpp
  26. 3 6
      src/modules/data/wrap_CompressedData.h
  27. 4 1
      src/modules/data/wrap_Data.cpp
  28. 7 7
      src/modules/data/wrap_Data.h
  29. 357 0
      src/modules/data/wrap_DataModule.cpp
  30. 37 0
      src/modules/data/wrap_DataModule.h
  31. 46 0
      src/modules/data/wrap_DataView.cpp
  32. 36 0
      src/modules/data/wrap_DataView.h
  33. 2 2
      src/modules/filesystem/wrap_FileData.cpp
  34. 2 2
      src/modules/filesystem/wrap_Filesystem.cpp
  35. 1 1
      src/modules/font/wrap_Font.cpp
  36. 1 1
      src/modules/font/wrap_GlyphData.cpp
  37. 1 1
      src/modules/font/wrap_GlyphData.h
  38. 1 1
      src/modules/font/wrap_Rasterizer.cpp
  39. 2 2
      src/modules/image/wrap_CompressedImageData.cpp
  40. 2 2
      src/modules/image/wrap_Image.cpp
  41. 2 2
      src/modules/image/wrap_ImageData.cpp
  42. 12 6
      src/modules/love/love.cpp
  43. 0 186
      src/modules/math/MathModule.cpp
  44. 0 63
      src/modules/math/MathModule.h
  45. 14 96
      src/modules/math/wrap_Math.cpp
  46. 2 2
      src/modules/sound/wrap_SoundData.cpp
  47. 2 0
      src/scripts/boot.lua
  48. 2 0
      src/scripts/boot.lua.h
  49. 1 1
      src/scripts/nogame.lua
  50. 1 1
      src/scripts/nogame.lua.h

+ 42 - 18
CMakeLists.txt

@@ -297,8 +297,6 @@ set(LOVE_SRC_COMMON
 	#src/common/Vector.cpp # Vector.cpp is empty.
 	src/common/Vector.h
 	src/common/version.h
-	src/common/wrap_Data.cpp
-	src/common/wrap_Data.h
 )
 
 if (APPLE)
@@ -366,6 +364,37 @@ source_group("modules\\audio" FILES ${LOVE_SRC_MODULE_AUDIO_ROOT})
 source_group("modules\\audio\\null" FILES ${LOVE_SRC_MODULE_AUDIO_NULL})
 source_group("modules\\audio\\openal" FILES ${LOVE_SRC_MODULE_AUDIO_OPENAL})
 
+#
+# love.data
+#
+
+set(LOVE_SRC_MODULE_DATA
+	src/modules/data/ByteData.cpp
+	src/modules/data/ByteData.h
+	src/modules/data/CompressedData.cpp
+	src/modules/data/CompressedData.h
+	src/modules/data/Compressor.cpp
+	src/modules/data/Compressor.h
+	src/modules/data/DataModule.cpp
+	src/modules/data/DataModule.h
+	src/modules/data/DataView.cpp
+	src/modules/data/DataView.h
+	src/modules/data/HashFunction.cpp
+	src/modules/data/HashFunction.h
+	src/modules/data/wrap_ByteData.cpp
+	src/modules/data/wrap_ByteData.h
+	src/modules/data/wrap_CompressedData.cpp
+	src/modules/data/wrap_CompressedData.h
+	src/modules/data/wrap_Data.cpp
+	src/modules/data/wrap_Data.h
+	src/modules/data/wrap_DataModule.cpp
+	src/modules/data/wrap_DataModule.h
+	src/modules/data/wrap_DataView.cpp
+	src/modules/data/wrap_DataView.h
+)
+
+source_group("modules\\data" FILES ${LOVE_SRC_MODULE_DATA})
+
 #
 # love.event
 #
@@ -686,12 +715,6 @@ source_group("modules\\keyboard\\sdl" FILES ${LOVE_SRC_MODULE_KEYBOARD_SDL})
 set(LOVE_SRC_MODULE_MATH
 	src/modules/math/BezierCurve.cpp
 	src/modules/math/BezierCurve.h
-	src/modules/math/CompressedData.cpp
-	src/modules/math/CompressedData.h
-	src/modules/math/Compressor.cpp
-	src/modules/math/Compressor.h
-	src/modules/math/HashFunction.cpp
-	src/modules/math/HashFunction.h
 	src/modules/math/MathModule.cpp
 	src/modules/math/MathModule.h
 	src/modules/math/RandomGenerator.cpp
@@ -700,8 +723,6 @@ set(LOVE_SRC_MODULE_MATH
 	src/modules/math/Transform.h
 	src/modules/math/wrap_BezierCurve.cpp
 	src/modules/math/wrap_BezierCurve.h
-	src/modules/math/wrap_CompressedData.cpp
-	src/modules/math/wrap_CompressedData.h
 	src/modules/math/wrap_Math.cpp
 	src/modules/math/wrap_Math.h
 	src/modules/math/wrap_RandomGenerator.cpp
@@ -1480,17 +1501,19 @@ add_library(love_3p_luasocket ${LOVE_SRC_3P_LUASOCKET})
 target_link_libraries(love_3p_luasocket ${LOVE_LUA_LIBRARY} ${LOVE_LINK_L3P_LUASOCKET_LIBLUASOCKET})
 
 #
-# Lua 5.3's UTF-8 library
+# APIs from Lua 5.3
 #
 
-set(LOVE_SRC_3P_LUAUTF8
-	src/libraries/luautf8/lprefix.h
-	src/libraries/luautf8/lutf8lib.c
-	src/libraries/luautf8/lutf8lib.h
+set(LOVE_SRC_3P_LUA53
+	src/libraries/lua53/lprefix.h
+	src/libraries/lua53/lstrlib.c
+	src/libraries/lua53/lstrlib.h
+	src/libraries/lua53/lutf8lib.c
+	src/libraries/lua53/lutf8lib.h
 )
 
-add_library(love_3p_luautf8 ${LOVE_SRC_3P_LUAUTF8})
-target_link_libraries(love_3p_luautf8 ${LOVE_LUA_LIBRARY})
+add_library(love_3p_lua53 ${LOVE_SRC_3P_LUA53})
+target_link_libraries(love_3p_lua53 ${LOVE_LUA_LIBRARY})
 
 #
 # lz4
@@ -1594,7 +1617,7 @@ set(LOVE_3P
 	love_3p_glslang
 	love_3p_lodepng
 	love_3p_luasocket
-	love_3p_luautf8
+	love_3p_lua53
 	love_3p_lz4
 	love_3p_noise1234
 	love_3p_wuff
@@ -1610,6 +1633,7 @@ set(LOVE_LIB_SRC
 	${LOVE_SRC_COMMON}
 	# Modules
 	${LOVE_SRC_MODULE_AUDIO}
+	${LOVE_SRC_MODULE_DATA}
 	${LOVE_SRC_MODULE_EVENT}
 	${LOVE_SRC_MODULE_FILESYSTEM}
 	${LOVE_SRC_MODULE_FONT}

+ 25 - 0
license.txt

@@ -110,6 +110,31 @@ POSSIBILITY OF SUCH DAMAGE.
 
 ---------
 
+This software uses portions of Kepler Project's lua-compat-5.3:
+
+The MIT License (MIT)
+
+Copyright (c) 2015 Kepler Project.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+---------
+
 This software uses lua-enet:
 
 Copyright (C) 2011 by Leaf Corcoran

+ 144 - 72
platform/xcode/liblove.xcodeproj/project.pbxproj

@@ -111,9 +111,6 @@
 		FA0B79471A958E3B000E1D17 /* Vector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B79161A958E3B000E1D17 /* Vector.cpp */; };
 		FA0B79481A958E3B000E1D17 /* Vector.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B79171A958E3B000E1D17 /* Vector.h */; };
 		FA0B79491A958E3B000E1D17 /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B79181A958E3B000E1D17 /* version.h */; };
-		FA0B794A1A958E3B000E1D17 /* wrap_Data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B79191A958E3B000E1D17 /* wrap_Data.cpp */; };
-		FA0B794B1A958E3B000E1D17 /* wrap_Data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B79191A958E3B000E1D17 /* wrap_Data.cpp */; };
-		FA0B794C1A958E3B000E1D17 /* wrap_Data.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B791A1A958E3B000E1D17 /* wrap_Data.h */; };
 		FA0B7A281A958EA3000E1D17 /* Box2D.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B794F1A958EA3000E1D17 /* Box2D.h */; };
 		FA0B7A291A958EA3000E1D17 /* b2BroadPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B79511A958EA3000E1D17 /* b2BroadPhase.cpp */; };
 		FA0B7A2A1A958EA3000E1D17 /* b2BroadPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B79511A958EA3000E1D17 /* b2BroadPhase.cpp */; };
@@ -297,10 +294,6 @@
 		FA0B7B211A958EA3000E1D17 /* luasocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7A0E1A958EA3000E1D17 /* luasocket.cpp */; };
 		FA0B7B221A958EA3000E1D17 /* luasocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7A0E1A958EA3000E1D17 /* luasocket.cpp */; };
 		FA0B7B231A958EA3000E1D17 /* luasocket.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7A0F1A958EA3000E1D17 /* luasocket.h */; };
-		FA0B7B241A958EA3000E1D17 /* lprefix.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7A111A958EA3000E1D17 /* lprefix.h */; };
-		FA0B7B251A958EA3000E1D17 /* lutf8lib.c in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7A121A958EA3000E1D17 /* lutf8lib.c */; };
-		FA0B7B261A958EA3000E1D17 /* lutf8lib.c in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7A121A958EA3000E1D17 /* lutf8lib.c */; };
-		FA0B7B271A958EA3000E1D17 /* lutf8lib.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7A131A958EA3000E1D17 /* lutf8lib.h */; };
 		FA0B7B281A958EA3000E1D17 /* simplexnoise1234.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7A151A958EA3000E1D17 /* simplexnoise1234.cpp */; };
 		FA0B7B291A958EA3000E1D17 /* simplexnoise1234.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA0B7A151A958EA3000E1D17 /* simplexnoise1234.cpp */; };
 		FA0B7B2A1A958EA3000E1D17 /* simplexnoise1234.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0B7A161A958EA3000E1D17 /* simplexnoise1234.h */; };
@@ -819,8 +812,6 @@
 		FA1BA0B31E16FD0800AA2803 /* Shader.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1BA0B01E16FD0800AA2803 /* Shader.h */; };
 		FA1BA0B71E17043400AA2803 /* wrap_Shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1BA0B51E17043400AA2803 /* wrap_Shader.cpp */; };
 		FA1BA0B81E17043400AA2803 /* wrap_Shader.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1BA0B61E17043400AA2803 /* wrap_Shader.h */; };
-		FA1DC2631C5D9555008F99A0 /* HashFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1DC2611C5D9555008F99A0 /* HashFunction.cpp */; };
-		FA1DC2641C5D9555008F99A0 /* HashFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1DC2621C5D9555008F99A0 /* HashFunction.h */; };
 		FA1E887E1DF363CD00E808AA /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1E887C1DF363CD00E808AA /* Filter.cpp */; };
 		FA1E887F1DF363CD00E808AA /* Filter.h in Headers */ = {isa = PBXBuildFile; fileRef = FA1E887D1DF363CD00E808AA /* Filter.h */; };
 		FA1E88801DF363D400E808AA /* Filter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1E887C1DF363CD00E808AA /* Filter.cpp */; };
@@ -855,7 +846,6 @@
 		FA41A3C81C0A1F950084430C /* ASTCHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA41A3C61C0A1F950084430C /* ASTCHandler.cpp */; };
 		FA41A3C91C0A1F950084430C /* ASTCHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA41A3C61C0A1F950084430C /* ASTCHandler.cpp */; };
 		FA41A3CA1C0A1F950084430C /* ASTCHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA41A3C71C0A1F950084430C /* ASTCHandler.h */; };
-		FA4943551D9DDFFE00E8D38A /* HashFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA1DC2611C5D9555008F99A0 /* HashFunction.cpp */; };
 		FA4B66C91ABBCF1900558F15 /* Timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA4B66C81ABBCF1900558F15 /* Timer.cpp */; };
 		FA4B66CA1ABBCF1900558F15 /* Timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA4B66C81ABBCF1900558F15 /* Timer.cpp */; };
 		FA4F2B791DE0125B00CA37D7 /* xxhash.c in Sources */ = {isa = PBXBuildFile; fileRef = FA4F2B771DE0125B00CA37D7 /* xxhash.c */; };
@@ -924,6 +914,20 @@
 		FA620A371AA2F8DB005DB4C2 /* wrap_Texture.h in Headers */ = {isa = PBXBuildFile; fileRef = FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */; };
 		FA620A3A1AA305F6005DB4C2 /* types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA620A391AA305F6005DB4C2 /* types.cpp */; };
 		FA620A3B1AA305F6005DB4C2 /* types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA620A391AA305F6005DB4C2 /* types.cpp */; };
+		FA6A2B661F5F7B6B0074C308 /* wrap_Data.h in Headers */ = {isa = PBXBuildFile; fileRef = FA6A2B641F5F7B6B0074C308 /* wrap_Data.h */; };
+		FA6A2B671F5F7B6B0074C308 /* wrap_Data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B651F5F7B6B0074C308 /* wrap_Data.cpp */; };
+		FA6A2B6A1F5F7F560074C308 /* DataView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B681F5F7F560074C308 /* DataView.cpp */; };
+		FA6A2B6B1F5F7F560074C308 /* DataView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B681F5F7F560074C308 /* DataView.cpp */; };
+		FA6A2B6C1F5F7F560074C308 /* DataView.h in Headers */ = {isa = PBXBuildFile; fileRef = FA6A2B691F5F7F560074C308 /* DataView.h */; };
+		FA6A2B6F1F5F845F0074C308 /* wrap_DataView.h in Headers */ = {isa = PBXBuildFile; fileRef = FA6A2B6D1F5F845F0074C308 /* wrap_DataView.h */; };
+		FA6A2B701F5F845F0074C308 /* wrap_DataView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B6E1F5F845F0074C308 /* wrap_DataView.cpp */; };
+		FA6A2B711F5F845F0074C308 /* wrap_DataView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B6E1F5F845F0074C308 /* wrap_DataView.cpp */; };
+		FA6A2B741F60B6710074C308 /* ByteData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B721F60B6710074C308 /* ByteData.cpp */; };
+		FA6A2B751F60B6710074C308 /* ByteData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B721F60B6710074C308 /* ByteData.cpp */; };
+		FA6A2B761F60B6710074C308 /* ByteData.h in Headers */ = {isa = PBXBuildFile; fileRef = FA6A2B731F60B6710074C308 /* ByteData.h */; };
+		FA6A2B791F60B8250074C308 /* wrap_ByteData.h in Headers */ = {isa = PBXBuildFile; fileRef = FA6A2B771F60B8250074C308 /* wrap_ByteData.h */; };
+		FA6A2B7A1F60B8250074C308 /* wrap_ByteData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B781F60B8250074C308 /* wrap_ByteData.cpp */; };
+		FA6A2B7B1F60B8250074C308 /* wrap_ByteData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA6A2B781F60B8250074C308 /* wrap_ByteData.cpp */; };
 		FA6BDE5C1F31725300786805 /* Color.h in Headers */ = {isa = PBXBuildFile; fileRef = FA6BDE5B1F31725300786805 /* Color.h */; };
 		FA7550A81AEBE276003E311E /* libluajit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA7550A71AEBE276003E311E /* libluajit.a */; };
 		FA76344A1E28722A0066EF9E /* StreamBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA7634481E28722A0066EF9E /* StreamBuffer.cpp */; };
@@ -960,19 +964,15 @@
 		FAA3A9AF1B7D465A00CED060 /* android.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAA3A9AC1B7D465A00CED060 /* android.cpp */; };
 		FAA3A9B01B7D465A00CED060 /* android.h in Headers */ = {isa = PBXBuildFile; fileRef = FAA3A9AD1B7D465A00CED060 /* android.h */; };
 		FAA627CE18E7E1560080752D /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAA627CD18E7E1560080752D /* CoreServices.framework */; };
+		FAAA3FD81F64B3AD00F89E99 /* lprefix.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAA3FD31F64B3AD00F89E99 /* lprefix.h */; };
+		FAAA3FD91F64B3AD00F89E99 /* lstrlib.c in Sources */ = {isa = PBXBuildFile; fileRef = FAAA3FD41F64B3AD00F89E99 /* lstrlib.c */; };
+		FAAA3FDA1F64B3AD00F89E99 /* lstrlib.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAA3FD51F64B3AD00F89E99 /* lstrlib.h */; };
+		FAAA3FDB1F64B3AD00F89E99 /* lutf8lib.c in Sources */ = {isa = PBXBuildFile; fileRef = FAAA3FD61F64B3AD00F89E99 /* lutf8lib.c */; };
+		FAAA3FDC1F64B3AD00F89E99 /* lutf8lib.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAA3FD71F64B3AD00F89E99 /* lutf8lib.h */; };
 		FAAFF04416CB11C700CCDE45 /* OpenAL-Soft.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */; };
-		FAB17BE01ABFAA2000F9BA27 /* Compressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BDE1ABFAA2000F9BA27 /* Compressor.cpp */; };
-		FAB17BE11ABFAA2000F9BA27 /* Compressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BDE1ABFAA2000F9BA27 /* Compressor.cpp */; };
-		FAB17BE21ABFAA2000F9BA27 /* Compressor.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB17BDF1ABFAA2000F9BA27 /* Compressor.h */; };
 		FAB17BE61ABFAA9000F9BA27 /* lz4.c in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BE41ABFAA9000F9BA27 /* lz4.c */; };
 		FAB17BE71ABFAA9000F9BA27 /* lz4.c in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BE41ABFAA9000F9BA27 /* lz4.c */; };
 		FAB17BE81ABFAA9000F9BA27 /* lz4.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB17BE51ABFAA9000F9BA27 /* lz4.h */; };
-		FAB17BEB1ABFAF1800F9BA27 /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BE91ABFAF1800F9BA27 /* CompressedData.cpp */; };
-		FAB17BEC1ABFAF1800F9BA27 /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BE91ABFAF1800F9BA27 /* CompressedData.cpp */; };
-		FAB17BED1ABFAF1800F9BA27 /* CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB17BEA1ABFAF1800F9BA27 /* CompressedData.h */; };
-		FAB17BF01ABFB37500F9BA27 /* wrap_CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BEE1ABFB37500F9BA27 /* wrap_CompressedData.cpp */; };
-		FAB17BF11ABFB37500F9BA27 /* wrap_CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BEE1ABFB37500F9BA27 /* wrap_CompressedData.cpp */; };
-		FAB17BF21ABFB37500F9BA27 /* wrap_CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB17BEF1ABFB37500F9BA27 /* wrap_CompressedData.h */; };
 		FAB17BF51ABFC4B100F9BA27 /* lz4hc.c in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BF31ABFC4B100F9BA27 /* lz4hc.c */; };
 		FAB17BF61ABFC4B100F9BA27 /* lz4hc.c in Sources */ = {isa = PBXBuildFile; fileRef = FAB17BF31ABFC4B100F9BA27 /* lz4hc.c */; };
 		FAB17BF71ABFC4B100F9BA27 /* lz4hc.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB17BF41ABFC4B100F9BA27 /* lz4hc.h */; };
@@ -985,6 +985,24 @@
 		FAC756FA1E4F99D200B91289 /* Effect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAC756F81E4F99D200B91289 /* Effect.cpp */; };
 		FAC756FB1E4F99D200B91289 /* Effect.h in Headers */ = {isa = PBXBuildFile; fileRef = FAC756F91E4F99D200B91289 /* Effect.h */; };
 		FAC756FC1E4F99DB00B91289 /* Effect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAC756F81E4F99D200B91289 /* Effect.cpp */; };
+		FACA02EC1F5E396B0084B28F /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E01F5E396B0084B28F /* CompressedData.cpp */; };
+		FACA02ED1F5E396B0084B28F /* CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FACA02E11F5E396B0084B28F /* CompressedData.h */; };
+		FACA02EE1F5E396B0084B28F /* Compressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E21F5E396B0084B28F /* Compressor.cpp */; };
+		FACA02EF1F5E396B0084B28F /* Compressor.h in Headers */ = {isa = PBXBuildFile; fileRef = FACA02E31F5E396B0084B28F /* Compressor.h */; };
+		FACA02F01F5E396B0084B28F /* DataModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E41F5E396B0084B28F /* DataModule.cpp */; };
+		FACA02F11F5E396B0084B28F /* DataModule.h in Headers */ = {isa = PBXBuildFile; fileRef = FACA02E51F5E396B0084B28F /* DataModule.h */; };
+		FACA02F21F5E396B0084B28F /* HashFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E61F5E396B0084B28F /* HashFunction.cpp */; };
+		FACA02F31F5E396B0084B28F /* HashFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = FACA02E71F5E396B0084B28F /* HashFunction.h */; };
+		FACA02F41F5E396B0084B28F /* wrap_CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E81F5E396B0084B28F /* wrap_CompressedData.cpp */; };
+		FACA02F51F5E396B0084B28F /* wrap_CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FACA02E91F5E396B0084B28F /* wrap_CompressedData.h */; };
+		FACA02F61F5E396B0084B28F /* wrap_DataModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02EA1F5E396B0084B28F /* wrap_DataModule.cpp */; };
+		FACA02F71F5E396B0084B28F /* wrap_DataModule.h in Headers */ = {isa = PBXBuildFile; fileRef = FACA02EB1F5E396B0084B28F /* wrap_DataModule.h */; };
+		FACA02F81F5E39760084B28F /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E01F5E396B0084B28F /* CompressedData.cpp */; };
+		FACA02F91F5E39790084B28F /* Compressor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E21F5E396B0084B28F /* Compressor.cpp */; };
+		FACA02FA1F5E397B0084B28F /* DataModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E41F5E396B0084B28F /* DataModule.cpp */; };
+		FACA02FB1F5E397E0084B28F /* HashFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E61F5E396B0084B28F /* HashFunction.cpp */; };
+		FACA02FC1F5E39810084B28F /* wrap_CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02E81F5E396B0084B28F /* wrap_CompressedData.cpp */; };
+		FACA02FD1F5E39840084B28F /* wrap_DataModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FACA02EA1F5E396B0084B28F /* wrap_DataModule.cpp */; };
 		FAD19A171DFF8CA200D5398A /* ImageDataBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAD19A151DFF8CA200D5398A /* ImageDataBase.cpp */; };
 		FAD19A181DFF8CA200D5398A /* ImageDataBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAD19A151DFF8CA200D5398A /* ImageDataBase.cpp */; };
 		FAD19A191DFF8CA200D5398A /* ImageDataBase.h in Headers */ = {isa = PBXBuildFile; fileRef = FAD19A161DFF8CA200D5398A /* ImageDataBase.h */; };
@@ -1238,8 +1256,6 @@
 		FA0B79161A958E3B000E1D17 /* Vector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Vector.cpp; sourceTree = "<group>"; };
 		FA0B79171A958E3B000E1D17 /* Vector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Vector.h; sourceTree = "<group>"; };
 		FA0B79181A958E3B000E1D17 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
-		FA0B79191A958E3B000E1D17 /* wrap_Data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Data.cpp; sourceTree = "<group>"; };
-		FA0B791A1A958E3B000E1D17 /* wrap_Data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Data.h; sourceTree = "<group>"; };
 		FA0B794F1A958EA3000E1D17 /* Box2D.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Box2D.h; sourceTree = "<group>"; };
 		FA0B79511A958EA3000E1D17 /* b2BroadPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b2BroadPhase.cpp; sourceTree = "<group>"; };
 		FA0B79521A958EA3000E1D17 /* b2BroadPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b2BroadPhase.h; sourceTree = "<group>"; };
@@ -1363,9 +1379,6 @@
 		FA0B79DA1A958EA3000E1D17 /* lodepng.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lodepng.h; sourceTree = "<group>"; };
 		FA0B7A0E1A958EA3000E1D17 /* luasocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = luasocket.cpp; sourceTree = "<group>"; };
 		FA0B7A0F1A958EA3000E1D17 /* luasocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = luasocket.h; sourceTree = "<group>"; };
-		FA0B7A111A958EA3000E1D17 /* lprefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lprefix.h; sourceTree = "<group>"; };
-		FA0B7A121A958EA3000E1D17 /* lutf8lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lutf8lib.c; sourceTree = "<group>"; };
-		FA0B7A131A958EA3000E1D17 /* lutf8lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lutf8lib.h; sourceTree = "<group>"; };
 		FA0B7A151A958EA3000E1D17 /* simplexnoise1234.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = simplexnoise1234.cpp; sourceTree = "<group>"; };
 		FA0B7A161A958EA3000E1D17 /* simplexnoise1234.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = simplexnoise1234.h; sourceTree = "<group>"; };
 		FA0B7A181A958EA3000E1D17 /* stb_image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stb_image.h; sourceTree = "<group>"; };
@@ -1718,8 +1731,6 @@
 		FA1BA0B01E16FD0800AA2803 /* Shader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Shader.h; sourceTree = "<group>"; };
 		FA1BA0B51E17043400AA2803 /* wrap_Shader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Shader.cpp; sourceTree = "<group>"; };
 		FA1BA0B61E17043400AA2803 /* wrap_Shader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Shader.h; sourceTree = "<group>"; };
-		FA1DC2611C5D9555008F99A0 /* HashFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashFunction.cpp; sourceTree = "<group>"; };
-		FA1DC2621C5D9555008F99A0 /* HashFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashFunction.h; sourceTree = "<group>"; };
 		FA1E887C1DF363CD00E808AA /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Filter.cpp; sourceTree = "<group>"; };
 		FA1E887D1DF363CD00E808AA /* Filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Filter.h; sourceTree = "<group>"; };
 		FA1E88811DF363DB00E808AA /* Filter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Filter.cpp; sourceTree = "<group>"; };
@@ -1789,6 +1800,16 @@
 		FA620A301AA2F8DB005DB4C2 /* wrap_Texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Texture.cpp; sourceTree = "<group>"; };
 		FA620A311AA2F8DB005DB4C2 /* wrap_Texture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Texture.h; sourceTree = "<group>"; };
 		FA620A391AA305F6005DB4C2 /* types.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = types.cpp; sourceTree = "<group>"; };
+		FA6A2B641F5F7B6B0074C308 /* wrap_Data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_Data.h; sourceTree = "<group>"; };
+		FA6A2B651F5F7B6B0074C308 /* wrap_Data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Data.cpp; sourceTree = "<group>"; };
+		FA6A2B681F5F7F560074C308 /* DataView.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DataView.cpp; sourceTree = "<group>"; };
+		FA6A2B691F5F7F560074C308 /* DataView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DataView.h; sourceTree = "<group>"; };
+		FA6A2B6D1F5F845F0074C308 /* wrap_DataView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_DataView.h; sourceTree = "<group>"; };
+		FA6A2B6E1F5F845F0074C308 /* wrap_DataView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_DataView.cpp; sourceTree = "<group>"; };
+		FA6A2B721F60B6710074C308 /* ByteData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ByteData.cpp; sourceTree = "<group>"; };
+		FA6A2B731F60B6710074C308 /* ByteData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByteData.h; sourceTree = "<group>"; };
+		FA6A2B771F60B8250074C308 /* wrap_ByteData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_ByteData.h; sourceTree = "<group>"; };
+		FA6A2B781F60B8250074C308 /* wrap_ByteData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_ByteData.cpp; sourceTree = "<group>"; };
 		FA6BDE5B1F31725300786805 /* Color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Color.h; sourceTree = "<group>"; };
 		FA7550A71AEBE276003E311E /* libluajit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libluajit.a; sourceTree = "<group>"; };
 		FA7634481E28722A0066EF9E /* StreamBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StreamBuffer.cpp; sourceTree = "<group>"; };
@@ -1815,15 +1836,14 @@
 		FAA3A9AC1B7D465A00CED060 /* android.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = android.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
 		FAA3A9AD1B7D465A00CED060 /* android.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = android.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
 		FAA627CD18E7E1560080752D /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; };
+		FAAA3FD31F64B3AD00F89E99 /* lprefix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lprefix.h; sourceTree = "<group>"; };
+		FAAA3FD41F64B3AD00F89E99 /* lstrlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lstrlib.c; sourceTree = "<group>"; };
+		FAAA3FD51F64B3AD00F89E99 /* lstrlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lstrlib.h; sourceTree = "<group>"; };
+		FAAA3FD61F64B3AD00F89E99 /* lutf8lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lutf8lib.c; sourceTree = "<group>"; };
+		FAAA3FD71F64B3AD00F89E99 /* lutf8lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lutf8lib.h; sourceTree = "<group>"; };
 		FAAFF04316CB11C700CCDE45 /* OpenAL-Soft.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "OpenAL-Soft.framework"; path = "/Library/Frameworks/OpenAL-Soft.framework"; sourceTree = "<absolute>"; };
-		FAB17BDE1ABFAA2000F9BA27 /* Compressor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Compressor.cpp; sourceTree = "<group>"; };
-		FAB17BDF1ABFAA2000F9BA27 /* Compressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Compressor.h; sourceTree = "<group>"; };
 		FAB17BE41ABFAA9000F9BA27 /* lz4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lz4.c; sourceTree = "<group>"; };
 		FAB17BE51ABFAA9000F9BA27 /* lz4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lz4.h; sourceTree = "<group>"; };
-		FAB17BE91ABFAF1800F9BA27 /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = "<group>"; };
-		FAB17BEA1ABFAF1800F9BA27 /* CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedData.h; sourceTree = "<group>"; };
-		FAB17BEE1ABFB37500F9BA27 /* wrap_CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_CompressedData.cpp; sourceTree = "<group>"; };
-		FAB17BEF1ABFB37500F9BA27 /* wrap_CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_CompressedData.h; sourceTree = "<group>"; };
 		FAB17BF31ABFC4B100F9BA27 /* lz4hc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lz4hc.c; sourceTree = "<group>"; };
 		FAB17BF41ABFC4B100F9BA27 /* lz4hc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lz4hc.h; sourceTree = "<group>"; };
 		FAB2D5A81AABDD8A008224A4 /* TrueTypeRasterizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrueTypeRasterizer.cpp; sourceTree = "<group>"; };
@@ -1834,6 +1854,18 @@
 		FAC756F41E4F99B400B91289 /* Effect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Effect.h; sourceTree = "<group>"; };
 		FAC756F81E4F99D200B91289 /* Effect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Effect.cpp; sourceTree = "<group>"; };
 		FAC756F91E4F99D200B91289 /* Effect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Effect.h; sourceTree = "<group>"; };
+		FACA02E01F5E396B0084B28F /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = "<group>"; };
+		FACA02E11F5E396B0084B28F /* CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedData.h; sourceTree = "<group>"; };
+		FACA02E21F5E396B0084B28F /* Compressor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Compressor.cpp; sourceTree = "<group>"; };
+		FACA02E31F5E396B0084B28F /* Compressor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Compressor.h; sourceTree = "<group>"; };
+		FACA02E41F5E396B0084B28F /* DataModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DataModule.cpp; sourceTree = "<group>"; };
+		FACA02E51F5E396B0084B28F /* DataModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataModule.h; sourceTree = "<group>"; };
+		FACA02E61F5E396B0084B28F /* HashFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashFunction.cpp; sourceTree = "<group>"; };
+		FACA02E71F5E396B0084B28F /* HashFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashFunction.h; sourceTree = "<group>"; };
+		FACA02E81F5E396B0084B28F /* wrap_CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_CompressedData.cpp; sourceTree = "<group>"; };
+		FACA02E91F5E396B0084B28F /* wrap_CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_CompressedData.h; sourceTree = "<group>"; };
+		FACA02EA1F5E396B0084B28F /* wrap_DataModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_DataModule.cpp; sourceTree = "<group>"; };
+		FACA02EB1F5E396B0084B28F /* wrap_DataModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_DataModule.h; sourceTree = "<group>"; };
 		FAD19A151DFF8CA200D5398A /* ImageDataBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDataBase.cpp; sourceTree = "<group>"; };
 		FAD19A161DFF8CA200D5398A /* ImageDataBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDataBase.h; sourceTree = "<group>"; };
 		FADF53F61E3C7ACD00012CC0 /* Buffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Buffer.cpp; sourceTree = "<group>"; };
@@ -2073,8 +2105,6 @@
 				FA0B79161A958E3B000E1D17 /* Vector.cpp */,
 				FA0B79171A958E3B000E1D17 /* Vector.h */,
 				FA0B79181A958E3B000E1D17 /* version.h */,
-				FA0B79191A958E3B000E1D17 /* wrap_Data.cpp */,
-				FA0B791A1A958E3B000E1D17 /* wrap_Data.h */,
 			);
 			name = common;
 			path = ../../src/common;
@@ -2089,8 +2119,8 @@
 				FA0B79D31A958EA3000E1D17 /* glad */,
 				FAF13FBF1E20934C00F898D2 /* glslang */,
 				FA0B79D81A958EA3000E1D17 /* lodepng */,
+				FAAA3FD21F64B3AD00F89E99 /* lua53 */,
 				FA0B79DB1A958EA3000E1D17 /* luasocket */,
-				FA0B7A101A958EA3000E1D17 /* luautf8 */,
 				FAB17BE31ABFAA9000F9BA27 /* lz4 */,
 				FA0B7A141A958EA3000E1D17 /* noise1234 */,
 				FA0B7A171A958EA3000E1D17 /* stb */,
@@ -2413,16 +2443,6 @@
 			path = libluasocket;
 			sourceTree = "<group>";
 		};
-		FA0B7A101A958EA3000E1D17 /* luautf8 */ = {
-			isa = PBXGroup;
-			children = (
-				FA0B7A111A958EA3000E1D17 /* lprefix.h */,
-				FA0B7A121A958EA3000E1D17 /* lutf8lib.c */,
-				FA0B7A131A958EA3000E1D17 /* lutf8lib.h */,
-			);
-			path = luautf8;
-			sourceTree = "<group>";
-		};
 		FA0B7A141A958EA3000E1D17 /* noise1234 */ = {
 			isa = PBXGroup;
 			children = (
@@ -2480,6 +2500,7 @@
 			isa = PBXGroup;
 			children = (
 				FA0B7B3D1A95902C000E1D17 /* audio */,
+				FACA02DF1F5E396B0084B28F /* data */,
 				FA0B7B521A95902C000E1D17 /* event */,
 				FA0B7B5A1A95902C000E1D17 /* filesystem */,
 				FA0B7B701A95902C000E1D17 /* font */,
@@ -2870,12 +2891,6 @@
 			children = (
 				FA0B7C011A95902C000E1D17 /* BezierCurve.cpp */,
 				FA0B7C021A95902C000E1D17 /* BezierCurve.h */,
-				FAB17BE91ABFAF1800F9BA27 /* CompressedData.cpp */,
-				FAB17BEA1ABFAF1800F9BA27 /* CompressedData.h */,
-				FAB17BDE1ABFAA2000F9BA27 /* Compressor.cpp */,
-				FAB17BDF1ABFAA2000F9BA27 /* Compressor.h */,
-				FA1DC2611C5D9555008F99A0 /* HashFunction.cpp */,
-				FA1DC2621C5D9555008F99A0 /* HashFunction.h */,
 				FA0B7C031A95902C000E1D17 /* MathModule.cpp */,
 				FA0B7C041A95902C000E1D17 /* MathModule.h */,
 				FA0B7C051A95902C000E1D17 /* RandomGenerator.cpp */,
@@ -2884,8 +2899,6 @@
 				FA4F2BE01DE6650600CA37D7 /* Transform.h */,
 				FA0B7C071A95902C000E1D17 /* wrap_BezierCurve.cpp */,
 				FA0B7C081A95902C000E1D17 /* wrap_BezierCurve.h */,
-				FAB17BEE1ABFB37500F9BA27 /* wrap_CompressedData.cpp */,
-				FAB17BEF1ABFB37500F9BA27 /* wrap_CompressedData.h */,
 				FA0B7C091A95902C000E1D17 /* wrap_Math.cpp */,
 				FA0B7C0A1A95902C000E1D17 /* wrap_Math.h */,
 				FA7DA04C1C16874A0056B200 /* wrap_Math.lua */,
@@ -3351,6 +3364,18 @@
 			path = ios/libraries/luajit;
 			sourceTree = "<group>";
 		};
+		FAAA3FD21F64B3AD00F89E99 /* lua53 */ = {
+			isa = PBXGroup;
+			children = (
+				FAAA3FD31F64B3AD00F89E99 /* lprefix.h */,
+				FAAA3FD41F64B3AD00F89E99 /* lstrlib.c */,
+				FAAA3FD51F64B3AD00F89E99 /* lstrlib.h */,
+				FAAA3FD61F64B3AD00F89E99 /* lutf8lib.c */,
+				FAAA3FD71F64B3AD00F89E99 /* lutf8lib.h */,
+			);
+			path = lua53;
+			sourceTree = "<group>";
+		};
 		FAB17BE31ABFAA9000F9BA27 /* lz4 */ = {
 			isa = PBXGroup;
 			children = (
@@ -3362,6 +3387,35 @@
 			path = lz4;
 			sourceTree = "<group>";
 		};
+		FACA02DF1F5E396B0084B28F /* data */ = {
+			isa = PBXGroup;
+			children = (
+				FA6A2B721F60B6710074C308 /* ByteData.cpp */,
+				FA6A2B731F60B6710074C308 /* ByteData.h */,
+				FACA02E01F5E396B0084B28F /* CompressedData.cpp */,
+				FACA02E11F5E396B0084B28F /* CompressedData.h */,
+				FACA02E21F5E396B0084B28F /* Compressor.cpp */,
+				FACA02E31F5E396B0084B28F /* Compressor.h */,
+				FACA02E41F5E396B0084B28F /* DataModule.cpp */,
+				FACA02E51F5E396B0084B28F /* DataModule.h */,
+				FA6A2B681F5F7F560074C308 /* DataView.cpp */,
+				FA6A2B691F5F7F560074C308 /* DataView.h */,
+				FACA02E61F5E396B0084B28F /* HashFunction.cpp */,
+				FACA02E71F5E396B0084B28F /* HashFunction.h */,
+				FA6A2B781F60B8250074C308 /* wrap_ByteData.cpp */,
+				FA6A2B771F60B8250074C308 /* wrap_ByteData.h */,
+				FACA02E81F5E396B0084B28F /* wrap_CompressedData.cpp */,
+				FACA02E91F5E396B0084B28F /* wrap_CompressedData.h */,
+				FA6A2B651F5F7B6B0074C308 /* wrap_Data.cpp */,
+				FA6A2B641F5F7B6B0074C308 /* wrap_Data.h */,
+				FACA02EA1F5E396B0084B28F /* wrap_DataModule.cpp */,
+				FACA02EB1F5E396B0084B28F /* wrap_DataModule.h */,
+				FA6A2B6E1F5F845F0074C308 /* wrap_DataView.cpp */,
+				FA6A2B6D1F5F845F0074C308 /* wrap_DataView.h */,
+			);
+			path = data;
+			sourceTree = "<group>";
+		};
 		FAF13FBF1E20934C00F898D2 /* glslang */ = {
 			isa = PBXGroup;
 			children = (
@@ -3542,15 +3596,15 @@
 				FA0B7D241A95902C000E1D17 /* Vera.ttf.h in Headers */,
 				FADF54311E3DABF600012CC0 /* SpriteBatch.h in Headers */,
 				FA0B7E5F1A95902C000E1D17 /* wrap_MouseJoint.h in Headers */,
-				FAB17BED1ABFAF1800F9BA27 /* CompressedData.h in Headers */,
 				217DFC0C1D9F6D490055D849 /* unixtcp.h in Headers */,
 				FA76344C1E28722A0066EF9E /* StreamBuffer.h in Headers */,
+				FA6A2B761F60B6710074C308 /* ByteData.h in Headers */,
 				217DFBF31D9F6D490055D849 /* mime.h in Headers */,
 				FA0B7B361A958EA3000E1D17 /* wuff_convert.h in Headers */,
 				FA0B7CDE1A95902C000E1D17 /* Source.h in Headers */,
 				FA0B7E141A95902C000E1D17 /* GearJoint.h in Headers */,
 				FA0B7D051A95902C000E1D17 /* wrap_DroppedFile.h in Headers */,
-				FA0B7B271A958EA3000E1D17 /* lutf8lib.h in Headers */,
+				FAAA3FDA1F64B3AD00F89E99 /* lstrlib.h in Headers */,
 				FA0B7E9F1A95902C000E1D17 /* WaveDecoder.h in Headers */,
 				FAF140871E20934C00F898D2 /* parseVersions.h in Headers */,
 				FA0B7AC61A958EA3000E1D17 /* types.h in Headers */,
@@ -3590,12 +3644,15 @@
 				FAB17BF71ABFC4B100F9BA27 /* lz4hc.h in Headers */,
 				FA0B7E831A95902C000E1D17 /* Shape.h in Headers */,
 				FAE272531C05A15B00A67640 /* ParticleSystem.h in Headers */,
+				FA6A2B6C1F5F7F560074C308 /* DataView.h in Headers */,
 				FAF140701E20934C00F898D2 /* Initialize.h in Headers */,
+				FAAA3FDC1F64B3AD00F89E99 /* lutf8lib.h in Headers */,
 				FA1BA09F1E16CFCE00AA2803 /* Font.h in Headers */,
 				FA0B7EDD1A95902D000E1D17 /* Touch.h in Headers */,
 				FA0B7EDE1A95902D000E1D17 /* Touch.h in Headers */,
 				FA0B7A541A958EA3000E1D17 /* b2Math.h in Headers */,
 				217DFBEE1D9F6D490055D849 /* luasocket.h in Headers */,
+				FACA02F31F5E396B0084B28F /* HashFunction.h in Headers */,
 				FA0B7ED01A95902C000E1D17 /* wrap_LuaThread.h in Headers */,
 				FA9159201CF1ED7500A7053F /* halffloat.h in Headers */,
 				FA0B7CE41A95902C000E1D17 /* wrap_Audio.h in Headers */,
@@ -3614,6 +3671,7 @@
 				FA0B7CFF1A95902C000E1D17 /* File.h in Headers */,
 				FA0B7AB41A958EA3000E1D17 /* ddsinfo.h in Headers */,
 				FA0B7DD21A95902C000E1D17 /* love.h in Headers */,
+				FA6A2B6F1F5F845F0074C308 /* wrap_DataView.h in Headers */,
 				FAF140861E20934C00F898D2 /* ParseHelper.h in Headers */,
 				FA0B7CE71A95902C000E1D17 /* wrap_Source.h in Headers */,
 				FA0B7B231A958EA3000E1D17 /* luasocket.h in Headers */,
@@ -3625,7 +3683,7 @@
 				FA0B7EE11A95902D000E1D17 /* wrap_Touch.h in Headers */,
 				FA9D8DDB1DEF8411002CD881 /* Stream.h in Headers */,
 				FA0B7AA91A958EA3000E1D17 /* b2RopeJoint.h in Headers */,
-				FAB17BE21ABFAA2000F9BA27 /* Compressor.h in Headers */,
+				FACA02F71F5E396B0084B28F /* wrap_DataModule.h in Headers */,
 				FA0B7E441A95902C000E1D17 /* wrap_CircleShape.h in Headers */,
 				FA0B7EB41A95902C000E1D17 /* System.h in Headers */,
 				FAF1405A1E20934C00F898D2 /* ConstantUnion.h in Headers */,
@@ -3642,10 +3700,10 @@
 				FA0B7AAF1A958EA3000E1D17 /* b2WheelJoint.h in Headers */,
 				FA0B7D1A1A95902C000E1D17 /* TrueTypeRasterizer.h in Headers */,
 				FA0B7EA81A95902C000E1D17 /* wrap_Decoder.h in Headers */,
-				FA1DC2641C5D9555008F99A0 /* HashFunction.h in Headers */,
 				FA0B7AC51A958EA3000E1D17 /* time.h in Headers */,
 				FA0B793E1A958E3B000E1D17 /* StringMap.h in Headers */,
 				FA0B793A1A958E3B000E1D17 /* Reference.h in Headers */,
+				FACA02F51F5E396B0084B28F /* wrap_CompressedData.h in Headers */,
 				FA0B7DCC1A95902C000E1D17 /* Keyboard.h in Headers */,
 				FA620A341AA2F8DB005DB4C2 /* wrap_Quad.h in Headers */,
 				FA0B7EA51A95902C000E1D17 /* SoundData.h in Headers */,
@@ -3678,6 +3736,7 @@
 				FA4F2BE41DE6650600CA37D7 /* Transform.h in Headers */,
 				FA0B7E0E1A95902C000E1D17 /* Fixture.h in Headers */,
 				FA0B7A401A958EA3000E1D17 /* b2ChainShape.h in Headers */,
+				FA6A2B661F5F7B6B0074C308 /* wrap_Data.h in Headers */,
 				217DFBE81D9F6D490055D849 /* inet.h in Headers */,
 				FADF53FA1E3C7ACD00012CC0 /* Buffer.h in Headers */,
 				FA0B7AA61A958EA3000E1D17 /* b2RevoluteJoint.h in Headers */,
@@ -3730,10 +3789,10 @@
 				FA0B7E531A95902C000E1D17 /* wrap_FrictionJoint.h in Headers */,
 				FA0B7EB71A95902C000E1D17 /* wrap_System.h in Headers */,
 				FA27B3A91B498151008A9DCE /* Video.h in Headers */,
+				FAAA3FD81F64B3AD00F89E99 /* lprefix.h in Headers */,
 				217DFBFA1D9F6D490055D849 /* select.h in Headers */,
 				FA0B7DF61A95902C000E1D17 /* wrap_Mouse.h in Headers */,
 				FAF140661E20934C00F898D2 /* gl_types.h in Headers */,
-				FAB17BF21ABFB37500F9BA27 /* wrap_CompressedData.h in Headers */,
 				FA0B7E801A95902C000E1D17 /* Joint.h in Headers */,
 				FA0B7D2F1A95902C000E1D17 /* Drawable.h in Headers */,
 				217DFBE21D9F6D490055D849 /* ftp.lua.h in Headers */,
@@ -3748,6 +3807,7 @@
 				FA0B7B2C1A958EA3000E1D17 /* checked.h in Headers */,
 				FADF54181E3DA08E00012CC0 /* Image.h in Headers */,
 				FA0B7D2A1A95902C000E1D17 /* wrap_GlyphData.h in Headers */,
+				FACA02F11F5E396B0084B28F /* DataModule.h in Headers */,
 				FA0B7E741A95902C000E1D17 /* wrap_Shape.h in Headers */,
 				FA0B7A5D1A958EA3000E1D17 /* b2Timer.h in Headers */,
 				FA91DA8D1F377C3900C80E33 /* deprecation.h in Headers */,
@@ -3777,6 +3837,7 @@
 				FA0B7E261A95902C000E1D17 /* PrismaticJoint.h in Headers */,
 				FA0B7E991A95902C000E1D17 /* Sound.h in Headers */,
 				FA0B7D841A95902C000E1D17 /* CompressedImageData.h in Headers */,
+				FACA02ED1F5E396B0084B28F /* CompressedData.h in Headers */,
 				FAF1407E1E20934C00F898D2 /* LiveTraverser.h in Headers */,
 				FA0B7D231A95902C000E1D17 /* Rasterizer.h in Headers */,
 				FAD19A191DFF8CA200D5398A /* ImageDataBase.h in Headers */,
@@ -3790,6 +3851,7 @@
 				FA0B7B2A1A958EA3000E1D17 /* simplexnoise1234.h in Headers */,
 				FA9D53AE1F5307E900125C6B /* Deprecations.h in Headers */,
 				FA0B7ADC1A958EA3000E1D17 /* glad.hpp in Headers */,
+				FA6A2B791F60B8250074C308 /* wrap_ByteData.h in Headers */,
 				FA0B7CF91A95902C000E1D17 /* FileData.h in Headers */,
 				FA0B7DA71A95902C000E1D17 /* PNGHandler.h in Headers */,
 				FA0B7AC41A958EA3000E1D17 /* protocol.h in Headers */,
@@ -3797,7 +3859,6 @@
 				FAF140A21E20934C00F898D2 /* RemoveTree.h in Headers */,
 				FA0B7A8E1A958EA3000E1D17 /* b2DistanceJoint.h in Headers */,
 				FA0B7A8B1A958EA3000E1D17 /* b2PolygonContact.h in Headers */,
-				FA0B794C1A958E3B000E1D17 /* wrap_Data.h in Headers */,
 				FA0B7D321A95902C000E1D17 /* Graphics.h in Headers */,
 				FA0B7E321A95902C000E1D17 /* Shape.h in Headers */,
 				FA620A371AA2F8DB005DB4C2 /* wrap_Texture.h in Headers */,
@@ -3805,7 +3866,6 @@
 				FA0B792E1A958E3B000E1D17 /* Memoizer.h in Headers */,
 				FA0B7A731A958EA3000E1D17 /* b2ChainAndCircleContact.h in Headers */,
 				FA0B7AA01A958EA3000E1D17 /* b2PrismaticJoint.h in Headers */,
-				FA0B7B241A958EA3000E1D17 /* lprefix.h in Headers */,
 				FA0B7DEA1A95902C000E1D17 /* Mouse.h in Headers */,
 				FA0B7E931A95902C000E1D17 /* ModPlugDecoder.h in Headers */,
 				FA0B7D111A95902C000E1D17 /* BMFontRasterizer.h in Headers */,
@@ -3824,6 +3884,7 @@
 				FA0B7A701A958EA3000E1D17 /* b2WorldCallbacks.h in Headers */,
 				FA0B7A9D1A958EA3000E1D17 /* b2MouseJoint.h in Headers */,
 				FA57FB9A1AE1993600F2AD6D /* noise1234.h in Headers */,
+				FACA02EF1F5E396B0084B28F /* Compressor.h in Headers */,
 				FA0B7CED1A95902C000E1D17 /* Event.h in Headers */,
 				FA0B7D811A95902C000E1D17 /* Volatile.h in Headers */,
 				FA0B7B2E1A958EA3000E1D17 /* unchecked.h in Headers */,
@@ -4020,12 +4081,14 @@
 				FA0B7A4F1A958EA3000E1D17 /* b2Draw.cpp in Sources */,
 				FAF140BC1E20934C00F898D2 /* ossource.cpp in Sources */,
 				FA0B7D7D1A95902C000E1D17 /* Texture.cpp in Sources */,
+				FACA02FB1F5E397E0084B28F /* HashFunction.cpp in Sources */,
 				FAF140A81E20934C00F898D2 /* ShaderLang.cpp in Sources */,
 				FA1BA09E1E16CFCE00AA2803 /* Font.cpp in Sources */,
 				FA0B7ECC1A95902C000E1D17 /* wrap_Channel.cpp in Sources */,
 				FA0B7E6D1A95902C000E1D17 /* wrap_RevoluteJoint.cpp in Sources */,
 				FA0B7A5F1A958EA3000E1D17 /* b2Body.cpp in Sources */,
 				FADF541C1E3DA46C00012CC0 /* wrap_Image.cpp in Sources */,
+				FACA02FA1F5E397B0084B28F /* DataModule.cpp in Sources */,
 				FA0B7E641A95902C000E1D17 /* wrap_PolygonShape.cpp in Sources */,
 				FA4F2C031DE936C200CA37D7 /* auxiliar.c in Sources */,
 				FA0B7E731A95902C000E1D17 /* wrap_Shape.cpp in Sources */,
@@ -4034,9 +4097,8 @@
 				FA0B7A751A958EA3000E1D17 /* b2ChainAndPolygonContact.cpp in Sources */,
 				FA0B7E6A1A95902C000E1D17 /* wrap_PulleyJoint.cpp in Sources */,
 				FA0B7DB81A95902C000E1D17 /* Joystick.cpp in Sources */,
-				FA0B794B1A958E3B000E1D17 /* wrap_Data.cpp in Sources */,
-				FAB17BEC1ABFAF1800F9BA27 /* CompressedData.cpp in Sources */,
 				FA91DA8C1F377C3900C80E33 /* deprecation.cpp in Sources */,
+				FA6A2B6B1F5F7F560074C308 /* DataView.cpp in Sources */,
 				FA0B7E401A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */,
 				FA0B7DEC1A95902C000E1D17 /* Cursor.cpp in Sources */,
 				FA0B7D871A95902C000E1D17 /* ImageData.cpp in Sources */,
@@ -4054,7 +4116,6 @@
 				FA0B7D1F1A95902C000E1D17 /* ImageRasterizer.cpp in Sources */,
 				FA0B7EA41A95902C000E1D17 /* SoundData.cpp in Sources */,
 				FA0B7D041A95902C000E1D17 /* wrap_DroppedFile.cpp in Sources */,
-				FA0B7B261A958EA3000E1D17 /* lutf8lib.c in Sources */,
 				FA0B7D461A95902C000E1D17 /* ParticleSystem.cpp in Sources */,
 				FAF1406A1E20934C00F898D2 /* glslang_tab.cpp in Sources */,
 				FA91591F1CF1ED7500A7053F /* halffloat.cpp in Sources */,
@@ -4071,6 +4132,7 @@
 				FAF1406F1E20934C00F898D2 /* Initialize.cpp in Sources */,
 				FA0B7E4F1A95902C000E1D17 /* wrap_Fixture.cpp in Sources */,
 				FA0B7EBF1A95902C000E1D17 /* Thread.cpp in Sources */,
+				FACA02F91F5E39790084B28F /* Compressor.cpp in Sources */,
 				FAF140811E20934C00F898D2 /* parseConst.cpp in Sources */,
 				FA4F2C121DE936FE00CA37D7 /* unixtcp.c in Sources */,
 				FA0B7EB91A95902C000E1D17 /* Channel.cpp in Sources */,
@@ -4109,6 +4171,7 @@
 				FA0B7CDD1A95902C000E1D17 /* Source.cpp in Sources */,
 				FA0B7DC51A95902C000E1D17 /* wrap_JoystickModule.cpp in Sources */,
 				FA0B7E701A95902C000E1D17 /* wrap_RopeJoint.cpp in Sources */,
+				FACA02FC1F5E39810084B28F /* wrap_CompressedData.cpp in Sources */,
 				FAF140AD1E20934C00F898D2 /* Versions.cpp in Sources */,
 				FA0B7A7B1A958EA3000E1D17 /* b2Contact.cpp in Sources */,
 				FA0B7A6F1A958EA3000E1D17 /* b2WorldCallbacks.cpp in Sources */,
@@ -4181,6 +4244,7 @@
 				FA0B7A811A958EA3000E1D17 /* b2EdgeAndCircleContact.cpp in Sources */,
 				FAF188A01E9DBC4B008C1479 /* depthstencil.cpp in Sources */,
 				FA0B7D071A95902C000E1D17 /* wrap_File.cpp in Sources */,
+				FA6A2B751F60B6710074C308 /* ByteData.cpp in Sources */,
 				FAD19A181DFF8CA200D5398A /* ImageDataBase.cpp in Sources */,
 				FA0B7AD01A958EA3000E1D17 /* peer.c in Sources */,
 				FA27B3C11B4985BF008A9DCE /* wrap_VideoStream.cpp in Sources */,
@@ -4210,7 +4274,6 @@
 				FA4F2C0D1DE936F100CA37D7 /* serial.c in Sources */,
 				FA0B7E0A1A95902C000E1D17 /* EdgeShape.cpp in Sources */,
 				FADF54301E3DABF600012CC0 /* SpriteBatch.cpp in Sources */,
-				FAB17BF11ABFB37500F9BA27 /* wrap_CompressedData.cpp in Sources */,
 				FA0B7CF81A95902C000E1D17 /* FileData.cpp in Sources */,
 				FA0B7DA61A95902C000E1D17 /* PNGHandler.cpp in Sources */,
 				FA0B7E981A95902C000E1D17 /* Sound.cpp in Sources */,
@@ -4233,7 +4296,6 @@
 				FA0B7E5E1A95902C000E1D17 /* wrap_MouseJoint.cpp in Sources */,
 				FA0B7B3B1A958EA3000E1D17 /* wuff_memory.c in Sources */,
 				FA0B79411A958E3B000E1D17 /* utf8.cpp in Sources */,
-				FAB17BE11ABFAA2000F9BA27 /* Compressor.cpp in Sources */,
 				FA0B7ADF1A958EA3000E1D17 /* lodepng.cpp in Sources */,
 				FA0B7D341A95902C000E1D17 /* Canvas.cpp in Sources */,
 				FAF140761E20934C00F898D2 /* IntermTraverse.cpp in Sources */,
@@ -4310,7 +4372,6 @@
 				FA0B7E611A95902C000E1D17 /* wrap_Physics.cpp in Sources */,
 				FA4F2C041DE936C600CA37D7 /* buffer.c in Sources */,
 				FA0B7DC81A95902C000E1D17 /* Keyboard.cpp in Sources */,
-				FA4943551D9DDFFE00E8D38A /* HashFunction.cpp in Sources */,
 				FA0B7EAD1A95902C000E1D17 /* wrap_SoundData.cpp in Sources */,
 				FA0B7E2E1A95902C000E1D17 /* RopeJoint.cpp in Sources */,
 				FA0B7CE01A95902C000E1D17 /* Source.cpp in Sources */,
@@ -4320,6 +4381,7 @@
 				FA0B7AA51A958EA3000E1D17 /* b2RevoluteJoint.cpp in Sources */,
 				FA0B7EA11A95902C000E1D17 /* Sound.cpp in Sources */,
 				FA0B7DE61A95902C000E1D17 /* Cursor.cpp in Sources */,
+				FA6A2B711F5F845F0074C308 /* wrap_DataView.cpp in Sources */,
 				FA0B7EDC1A95902D000E1D17 /* Touch.cpp in Sources */,
 				FA0B7CE91A95902C000E1D17 /* Event.cpp in Sources */,
 				FA4F2C131DE936FE00CA37D7 /* unixudp.c in Sources */,
@@ -4327,9 +4389,11 @@
 				FA0B7A961A958EA3000E1D17 /* b2Joint.cpp in Sources */,
 				FA0B7A621A958EA3000E1D17 /* b2ContactManager.cpp in Sources */,
 				FA0B7A2F1A958EA3000E1D17 /* b2CollideEdge.cpp in Sources */,
+				FACA02F81F5E39760084B28F /* CompressedData.cpp in Sources */,
 				FA0B7ADA1A958EA3000E1D17 /* glad.cpp in Sources */,
 				FAF140541E20934C00F898D2 /* CodeGen.cpp in Sources */,
 				FA0B7E1F1A95902C000E1D17 /* Physics.cpp in Sources */,
+				FA6A2B7B1F60B8250074C308 /* wrap_ByteData.cpp in Sources */,
 				FA0B7E821A95902C000E1D17 /* Shape.cpp in Sources */,
 				FA0B7ACE1A958EA3000E1D17 /* packet.c in Sources */,
 				FAF140891E20934C00F898D2 /* PoolAlloc.cpp in Sources */,
@@ -4337,6 +4401,7 @@
 				FA1E88801DF363D400E808AA /* Filter.cpp in Sources */,
 				FA0B7AA81A958EA3000E1D17 /* b2RopeJoint.cpp in Sources */,
 				FA0B7ACC1A958EA3000E1D17 /* list.c in Sources */,
+				FACA02FD1F5E39840084B28F /* wrap_DataModule.cpp in Sources */,
 				FA0B7DEF1A95902C000E1D17 /* Mouse.cpp in Sources */,
 				FA0B79251A958E3B000E1D17 /* Exception.cpp in Sources */,
 				FA0B7D291A95902C000E1D17 /* wrap_GlyphData.cpp in Sources */,
@@ -4379,12 +4444,14 @@
 				FA0B7D7C1A95902C000E1D17 /* Texture.cpp in Sources */,
 				FAF140BB1E20934C00F898D2 /* ossource.cpp in Sources */,
 				FA0B7ECB1A95902C000E1D17 /* wrap_Channel.cpp in Sources */,
+				FACA02F21F5E396B0084B28F /* HashFunction.cpp in Sources */,
 				FAF140A71E20934C00F898D2 /* ShaderLang.cpp in Sources */,
 				FA1BA09D1E16CFCE00AA2803 /* Font.cpp in Sources */,
 				FA0B7E6C1A95902C000E1D17 /* wrap_RevoluteJoint.cpp in Sources */,
 				FA0B7A5E1A958EA3000E1D17 /* b2Body.cpp in Sources */,
 				FA0B7E631A95902C000E1D17 /* wrap_PolygonShape.cpp in Sources */,
 				FADF541B1E3DA46C00012CC0 /* wrap_Image.cpp in Sources */,
+				FACA02F01F5E396B0084B28F /* DataModule.cpp in Sources */,
 				FA0B7E721A95902C000E1D17 /* wrap_Shape.cpp in Sources */,
 				FA0B7CFD1A95902C000E1D17 /* File.cpp in Sources */,
 				FA4F2BB01DE1E37B00CA37D7 /* RecordingDevice.cpp in Sources */,
@@ -4394,7 +4461,6 @@
 				FA0B7E691A95902C000E1D17 /* wrap_PulleyJoint.cpp in Sources */,
 				FA0B7DB71A95902C000E1D17 /* Joystick.cpp in Sources */,
 				FA0B7A321A958EA3000E1D17 /* b2Collision.cpp in Sources */,
-				FAB17BEB1ABFAF1800F9BA27 /* CompressedData.cpp in Sources */,
 				FA91DA8B1F377C3900C80E33 /* deprecation.cpp in Sources */,
 				FA0B7E3F1A95902C000E1D17 /* wrap_ChainShape.cpp in Sources */,
 				FA0B7DEB1A95902C000E1D17 /* Cursor.cpp in Sources */,
@@ -4430,6 +4496,7 @@
 				FAF1406E1E20934C00F898D2 /* Initialize.cpp in Sources */,
 				FA0B7EB81A95902C000E1D17 /* Channel.cpp in Sources */,
 				217DFC091D9F6D490055D849 /* unix.c in Sources */,
+				FACA02EE1F5E396B0084B28F /* Compressor.cpp in Sources */,
 				FAF140801E20934C00F898D2 /* parseConst.cpp in Sources */,
 				FA0B7AB11A958EA3000E1D17 /* b2Rope.cpp in Sources */,
 				FA4B66C91ABBCF1900558F15 /* Timer.cpp in Sources */,
@@ -4445,6 +4512,7 @@
 				FA0B7D3C1A95902C000E1D17 /* Image.cpp in Sources */,
 				FA0B7A8C1A958EA3000E1D17 /* b2DistanceJoint.cpp in Sources */,
 				FADF53FD1E3D74F200012CC0 /* Text.cpp in Sources */,
+				FA6A2B741F60B6710074C308 /* ByteData.cpp in Sources */,
 				217DFBE91D9F6D490055D849 /* io.c in Sources */,
 				FA0B7E421A95902C000E1D17 /* wrap_CircleShape.cpp in Sources */,
 				FA0B7CE51A95902C000E1D17 /* wrap_Source.cpp in Sources */,
@@ -4459,7 +4527,6 @@
 				FADF54021E3D77B500012CC0 /* wrap_Text.cpp in Sources */,
 				FA0B7ED11A95902C000E1D17 /* wrap_ThreadModule.cpp in Sources */,
 				FA0B7EDF1A95902D000E1D17 /* wrap_Touch.cpp in Sources */,
-				FA0B794A1A958E3B000E1D17 /* wrap_Data.cpp in Sources */,
 				217DFBFB1D9F6D490055D849 /* serial.c in Sources */,
 				FADF54251E3DA5BA00012CC0 /* Mesh.cpp in Sources */,
 				FA4F2BE51DE6650600CA37D7 /* wrap_Transform.cpp in Sources */,
@@ -4468,12 +4535,14 @@
 				FA0B7DC41A95902C000E1D17 /* wrap_JoystickModule.cpp in Sources */,
 				FA0B7E6F1A95902C000E1D17 /* wrap_RopeJoint.cpp in Sources */,
 				FA0B7AB51A958EA3000E1D17 /* ddsparse.cpp in Sources */,
+				FACA02F41F5E396B0084B28F /* wrap_CompressedData.cpp in Sources */,
 				FAF140AC1E20934C00F898D2 /* Versions.cpp in Sources */,
 				FA0B7A441A958EA3000E1D17 /* b2EdgeShape.cpp in Sources */,
 				FA0B79461A958E3B000E1D17 /* Vector.cpp in Sources */,
 				FA0B7DBB1A95902C000E1D17 /* Joystick.cpp in Sources */,
 				FAF140DB1E20934C00F898D2 /* InitializeDll.cpp in Sources */,
 				FA0B7DAE1A95902C000E1D17 /* wrap_CompressedImageData.cpp in Sources */,
+				FA6A2B701F5F845F0074C308 /* wrap_DataView.cpp in Sources */,
 				FA0B7A6E1A958EA3000E1D17 /* b2WorldCallbacks.cpp in Sources */,
 				FA0B7A831A958EA3000E1D17 /* b2EdgeAndPolygonContact.cpp in Sources */,
 				FA0B7AA11A958EA3000E1D17 /* b2PulleyJoint.cpp in Sources */,
@@ -4490,6 +4559,7 @@
 				FA0B7E031A95902C000E1D17 /* Contact.cpp in Sources */,
 				FA0B7D821A95902C000E1D17 /* CompressedImageData.cpp in Sources */,
 				FAF1409D1E20934C00F898D2 /* reflection.cpp in Sources */,
+				FAAA3FDB1F64B3AD00F89E99 /* lutf8lib.c in Sources */,
 				FAF1408A1E20934C00F898D2 /* Pp.cpp in Sources */,
 				FA76344A1E28722A0066EF9E /* StreamBuffer.cpp in Sources */,
 				FA0B7A7A1A958EA3000E1D17 /* b2Contact.cpp in Sources */,
@@ -4507,6 +4577,7 @@
 				FAF1409A1E20934C00F898D2 /* propagateNoContraction.cpp in Sources */,
 				FA0B7A9B1A958EA3000E1D17 /* b2MouseJoint.cpp in Sources */,
 				FA2AF6741DAD64970032B62C /* vertex.cpp in Sources */,
+				FA6A2B7A1F60B8250074C308 /* wrap_ByteData.cpp in Sources */,
 				FAF140551E20934C00F898D2 /* Link.cpp in Sources */,
 				FAF140841E20934C00F898D2 /* ParseHelper.cpp in Sources */,
 				FA0B7D7F1A95902C000E1D17 /* Volatile.cpp in Sources */,
@@ -4561,7 +4632,6 @@
 				FA0B7D251A95902C000E1D17 /* wrap_Font.cpp in Sources */,
 				FA0B7E091A95902C000E1D17 /* EdgeShape.cpp in Sources */,
 				FA0B7CF71A95902C000E1D17 /* FileData.cpp in Sources */,
-				FAB17BF01ABFB37500F9BA27 /* wrap_CompressedData.cpp in Sources */,
 				FA0B7DA51A95902C000E1D17 /* PNGHandler.cpp in Sources */,
 				FA0B7B371A958EA3000E1D17 /* wuff_internal.c in Sources */,
 				FA0B7E971A95902C000E1D17 /* Sound.cpp in Sources */,
@@ -4570,12 +4640,14 @@
 				FA0B7A471A958EA3000E1D17 /* b2PolygonShape.cpp in Sources */,
 				FADF542F1E3DABF600012CC0 /* SpriteBatch.cpp in Sources */,
 				FA0B7D8D1A95902C000E1D17 /* ddsHandler.cpp in Sources */,
+				FAAA3FD91F64B3AD00F89E99 /* lstrlib.c in Sources */,
 				FA0B7DFD1A95902C000E1D17 /* ChainShape.cpp in Sources */,
 				FA0B79201A958E3B000E1D17 /* delay.cpp in Sources */,
 				FA0B7A4B1A958EA3000E1D17 /* b2BlockAllocator.cpp in Sources */,
 				FA0B7A551A958EA3000E1D17 /* b2Settings.cpp in Sources */,
 				FA0B7EA91A95902C000E1D17 /* wrap_Sound.cpp in Sources */,
 				FA0B7A981A958EA3000E1D17 /* b2MotorJoint.cpp in Sources */,
+				FA6A2B671F5F7B6B0074C308 /* wrap_Data.cpp in Sources */,
 				FA0B7E061A95902C000E1D17 /* DistanceJoint.cpp in Sources */,
 				FA620A321AA2F8DB005DB4C2 /* wrap_Quad.cpp in Sources */,
 				FA4F2BA61DE1E36400CA37D7 /* RecordingDevice.cpp in Sources */,
@@ -4586,7 +4658,6 @@
 				FA0B7A741A958EA3000E1D17 /* b2ChainAndPolygonContact.cpp in Sources */,
 				FA0B7AD41A958EA3000E1D17 /* unix.c in Sources */,
 				FA0B7A771A958EA3000E1D17 /* b2CircleContact.cpp in Sources */,
-				FAB17BE01ABFAA2000F9BA27 /* Compressor.cpp in Sources */,
 				FADF543B1E3DAFF700012CC0 /* wrap_Graphics.cpp in Sources */,
 				FA0B7D331A95902C000E1D17 /* Canvas.cpp in Sources */,
 				FA0B7E941A95902C000E1D17 /* Mpg123Decoder.cpp in Sources */,
@@ -4628,6 +4699,7 @@
 				FA0B7E661A95902C000E1D17 /* wrap_PrismaticJoint.cpp in Sources */,
 				FA0B7DCD1A95902C000E1D17 /* wrap_Keyboard.cpp in Sources */,
 				FA0B7EE51A95902D000E1D17 /* Window.cpp in Sources */,
+				FA6A2B6A1F5F7F560074C308 /* DataView.cpp in Sources */,
 				FA0B7E391A95902C000E1D17 /* World.cpp in Sources */,
 				FA0B7ABD1A958EA3000E1D17 /* compress.c in Sources */,
 				FA0B7ACB1A958EA3000E1D17 /* list.c in Sources */,
@@ -4637,7 +4709,6 @@
 				FA0B7E881A95902C000E1D17 /* Decoder.cpp in Sources */,
 				FA0B7E3C1A95902C000E1D17 /* wrap_Body.cpp in Sources */,
 				FA0B7D791A95902C000E1D17 /* Quad.cpp in Sources */,
-				FA1DC2631C5D9555008F99A0 /* HashFunction.cpp in Sources */,
 				FAC756F51E4F99B400B91289 /* Effect.cpp in Sources */,
 				FA620A3A1AA305F6005DB4C2 /* types.cpp in Sources */,
 				FA0B7DD31A95902C000E1D17 /* BezierCurve.cpp in Sources */,
@@ -4685,7 +4756,7 @@
 				FA9D8DE01DEF843D002CD881 /* Image.cpp in Sources */,
 				FA0B7E811A95902C000E1D17 /* Shape.cpp in Sources */,
 				FA4F2BA81DE1E36400CA37D7 /* wrap_RecordingDevice.cpp in Sources */,
-				FA0B7B251A958EA3000E1D17 /* lutf8lib.c in Sources */,
+				FACA02EC1F5E396B0084B28F /* CompressedData.cpp in Sources */,
 				FAF140531E20934C00F898D2 /* CodeGen.cpp in Sources */,
 				FA27B3B31B498151008A9DCE /* wrap_Video.cpp in Sources */,
 				FA0B7A611A958EA3000E1D17 /* b2ContactManager.cpp in Sources */,
@@ -4696,6 +4767,7 @@
 				FA1E887E1DF363CD00E808AA /* Filter.cpp in Sources */,
 				FA0B7D281A95902C000E1D17 /* wrap_GlyphData.cpp in Sources */,
 				FA0B7DE21A95902C000E1D17 /* wrap_RandomGenerator.cpp in Sources */,
+				FACA02F61F5E396B0084B28F /* wrap_DataModule.cpp in Sources */,
 				FA0B79401A958E3B000E1D17 /* utf8.cpp in Sources */,
 				FA0B79241A958E3B000E1D17 /* Exception.cpp in Sources */,
 				FA0B7D0C1A95902C000E1D17 /* wrap_Filesystem.cpp in Sources */,

+ 2 - 1
src/common/Module.h

@@ -39,6 +39,7 @@ public:
 	enum ModuleType
 	{
 		M_AUDIO,
+		M_DATA,
 		M_EVENT,
 		M_FILESYSTEM,
 		M_FONT,
@@ -54,8 +55,8 @@ public:
 		M_THREAD,
 		M_TIMER,
 		M_TOUCH,
-		M_WINDOW,
 		M_VIDEO,
+		M_WINDOW,
 		M_MAX_ENUM
 	};
 

+ 2 - 1
src/common/config.h

@@ -139,6 +139,7 @@
 #else
 #	define LOVE_ENABLE_LOVE
 #	define LOVE_ENABLE_AUDIO
+#	define LOVE_ENABLE_DATA
 #	define LOVE_ENABLE_EVENT
 #	define LOVE_ENABLE_FILESYSTEM
 #	define LOVE_ENABLE_FONT
@@ -159,7 +160,7 @@
 
 #	define LOVE_ENABLE_ENET
 #	define LOVE_ENABLE_LUASOCKET
-#	define LOVE_ENABLE_LUAUTF8
+#	define LOVE_ENABLE_LUA53
 #endif
 
 // Check we have a sane configuration

+ 0 - 0
src/libraries/luautf8/lprefix.h → src/libraries/lua53/lprefix.h


+ 585 - 0
src/libraries/lua53/lstrlib.c

@@ -0,0 +1,585 @@
+/*
+** $Id: lstrlib.c,v 1.254 2016/12/22 13:08:50 roberto Exp $
+** Standard library for string operations and pattern-matching
+** Modified by the Kepler Project and the LOVE Development Team to work with
+** Lua 5.1's API
+*/
+
+/*********************************************************************
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015 Kepler Project.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *********************************************************************/
+
+/*********************************************************************
+ * This file contains parts of Lua 5.2's and Lua 5.3's source code:
+ *
+ * Copyright (C) 1994-2014 Lua.org, PUC-Rio.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *********************************************************************/
+
+#include "lprefix.h"
+
+
+#include <ctype.h>
+#include <float.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+#include "lstrlib.h"
+
+typedef size_t lua_Unsigned;
+
+
+static void luaL_buffinit_53 (lua_State *L, luaL_Buffer_53 *B) {
+	/* make it crash if used via pointer to a 5.1-style luaL_Buffer */
+	B->b.p = NULL;
+	B->b.L = NULL;
+	B->b.lvl = 0;
+	/* reuse the buffer from the 5.1-style luaL_Buffer though! */
+	B->ptr = B->b.buffer;
+	B->capacity = LUAL_BUFFERSIZE;
+	B->nelems = 0;
+	B->L2 = L;
+}
+
+
+static char *luaL_prepbuffsize_53 (luaL_Buffer_53 *B, size_t s) {
+	if (B->capacity - B->nelems < s) { /* needs to grow */
+		char* newptr = NULL;
+		size_t newcap = B->capacity * 2;
+		if (newcap - B->nelems < s)
+			newcap = B->nelems + s;
+		if (newcap < B->capacity) /* overflow */
+			luaL_error(B->L2, "buffer too large");
+		newptr = (char*)lua_newuserdata(B->L2, newcap);
+		memcpy(newptr, B->ptr, B->nelems);
+		if (B->ptr != B->b.buffer)
+			lua_replace(B->L2, -2); /* remove old buffer */
+		B->ptr = newptr;
+		B->capacity = newcap;
+	}
+	return B->ptr+B->nelems;
+}
+
+
+#define luaL_addsize_53(B, s) \
+	((B)->nelems += (s))
+
+#define luaL_addchar_53(B, c) \
+	((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize_53((B), 1)), \
+	((B)->ptr[(B)->nelems++] = (c)))
+
+
+static void luaL_addlstring_53 (luaL_Buffer_53 *B, const char *s, size_t l) {
+	memcpy(luaL_prepbuffsize_53(B, l), s, l);
+	luaL_addsize_53(B, l);
+}
+
+
+void lua53_pushresult (luaL_Buffer_53 *B) {
+	lua_pushlstring(B->L2, B->ptr, B->nelems);
+	if (B->ptr != B->b.buffer)
+		lua_replace(B->L2, -2); /* remove userdata buffer */
+}
+
+void lua53_cleanupbuffer (luaL_Buffer_53 *B) {
+	if (B->ptr != B->b.buffer)
+		lua_replace(B->L2, -1); /* remove userdata buffer */
+}
+
+/*
+** Some sizes are better limited to fit in 'int', but must also fit in
+** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.)
+*/
+#define MAX_SIZET	((size_t)(~(size_t)0))
+
+#define MAXSIZE  \
+	(sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX))
+
+
+/* translate a relative string position: negative means back from end */
+static lua_Integer posrelat (lua_Integer pos, size_t len) {
+  if (pos >= 0) return pos;
+  else if (0u - (size_t)pos > len) return 0;
+  else return (lua_Integer)len + pos + 1;
+}
+
+
+/*
+** {======================================================
+** PACK/UNPACK
+** =======================================================
+*/
+
+
+/* value used for padding */
+#if !defined(LUAL_PACKPADBYTE)
+#define LUAL_PACKPADBYTE		0x00
+#endif
+
+/* maximum size for the binary representation of an integer */
+#define MAXINTSIZE	16
+
+/* number of bits in a character */
+#define NB	CHAR_BIT
+
+/* mask for one character (NB 1's) */
+#define MC	((1 << NB) - 1)
+
+/* size of a lua_Integer */
+#define SZINT	((int)sizeof(lua_Integer))
+
+
+/* dummy union to get native endianness */
+static const union {
+  int dummy;
+  char little;  /* true iff machine is little endian */
+} nativeendian = {1};
+
+
+/* dummy structure to get native alignment requirements */
+struct cD {
+  char c;
+  union { double d; void *p; lua_Integer i; lua_Number n; } u;
+};
+
+#define MAXALIGN	(offsetof(struct cD, u))
+
+
+/*
+** Union for serializing floats
+*/
+typedef union Ftypes {
+  float f;
+  double d;
+  lua_Number n;
+  char buff[5 * sizeof(lua_Number)];  /* enough for any float type */
+} Ftypes;
+
+
+/*
+** information to pack/unpack stuff
+*/
+typedef struct Header {
+  lua_State *L;
+  int islittle;
+  int maxalign;
+} Header;
+
+
+/*
+** options for pack/unpack
+*/
+typedef enum KOption {
+  Kint,		/* signed integers */
+  Kuint,	/* unsigned integers */
+  Kfloat,	/* floating-point numbers */
+  Kchar,	/* fixed-length strings */
+  Kstring,	/* strings with prefixed length */
+  Kzstr,	/* zero-terminated strings */
+  Kpadding,	/* padding */
+  Kpaddalign,	/* padding for alignment */
+  Knop		/* no-op (configuration or spaces) */
+} KOption;
+
+
+/*
+** Read an integer numeral from string 'fmt' or return 'df' if
+** there is no numeral
+*/
+static int digit (int c) { return '0' <= c && c <= '9'; }
+
+static int getnum (const char **fmt, int df) {
+  if (!digit(**fmt))  /* no number? */
+    return df;  /* return default value */
+  else {
+    int a = 0;
+    do {
+      a = a*10 + (*((*fmt)++) - '0');
+    } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10);
+    return a;
+  }
+}
+
+
+/*
+** Read an integer numeral and raises an error if it is larger
+** than the maximum size for integers.
+*/
+static int getnumlimit (Header *h, const char **fmt, int df) {
+  int sz = getnum(fmt, df);
+  if (sz > MAXINTSIZE || sz <= 0)
+    luaL_error(h->L, "integral size (%d) out of limits [1,%d]",
+                     sz, MAXINTSIZE);
+  return sz;
+}
+
+
+/*
+** Initialize Header
+*/
+static void initheader (lua_State *L, Header *h) {
+  h->L = L;
+  h->islittle = nativeendian.little;
+  h->maxalign = 1;
+}
+
+
+/*
+** Read and classify next option. 'size' is filled with option's size.
+*/
+static KOption getoption (Header *h, const char **fmt, int *size) {
+  int opt = *((*fmt)++);
+  *size = 0;  /* default */
+  switch (opt) {
+    case 'b': *size = sizeof(char); return Kint;
+    case 'B': *size = sizeof(char); return Kuint;
+    case 'h': *size = sizeof(short); return Kint;
+    case 'H': *size = sizeof(short); return Kuint;
+    case 'l': *size = sizeof(long); return Kint;
+    case 'L': *size = sizeof(long); return Kuint;
+    case 'j': *size = sizeof(lua_Integer); return Kint;
+    case 'J': *size = sizeof(lua_Integer); return Kuint;
+    case 'T': *size = sizeof(size_t); return Kuint;
+    case 'f': *size = sizeof(float); return Kfloat;
+    case 'd': *size = sizeof(double); return Kfloat;
+    case 'n': *size = sizeof(lua_Number); return Kfloat;
+    case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint;
+    case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint;
+    case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring;
+    case 'c':
+      *size = getnum(fmt, -1);
+      if (*size == -1)
+        luaL_error(h->L, "missing size for format option 'c'");
+      return Kchar;
+    case 'z': return Kzstr;
+    case 'x': *size = 1; return Kpadding;
+    case 'X': return Kpaddalign;
+    case ' ': break;
+    case '<': h->islittle = 1; break;
+    case '>': h->islittle = 0; break;
+    case '=': h->islittle = nativeendian.little; break;
+    case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break;
+    default: luaL_error(h->L, "invalid format option '%c'", opt);
+  }
+  return Knop;
+}
+
+
+/*
+** Read, classify, and fill other details about the next option.
+** 'psize' is filled with option's size, 'notoalign' with its
+** alignment requirements.
+** Local variable 'size' gets the size to be aligned. (Kpadal option
+** always gets its full alignment, other options are limited by
+** the maximum alignment ('maxalign'). Kchar option needs no alignment
+** despite its size.
+*/
+static KOption getdetails (Header *h, size_t totalsize,
+                           const char **fmt, int *psize, int *ntoalign) {
+  KOption opt = getoption(h, fmt, psize);
+  int align = *psize;  /* usually, alignment follows size */
+  if (opt == Kpaddalign) {  /* 'X' gets alignment from following option */
+    if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0)
+      luaL_argerror(h->L, 1, "invalid next option for option 'X'");
+  }
+  if (align <= 1 || opt == Kchar)  /* need no alignment? */
+    *ntoalign = 0;
+  else {
+    if (align > h->maxalign)  /* enforce maximum alignment */
+      align = h->maxalign;
+    if ((align & (align - 1)) != 0)  /* is 'align' not a power of 2? */
+      luaL_argerror(h->L, 1, "format asks for alignment not power of 2");
+    *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1);
+  }
+  return opt;
+}
+
+
+/*
+** Pack integer 'n' with 'size' bytes and 'islittle' endianness.
+** The final 'if' handles the case when 'size' is larger than
+** the size of a Lua integer, correcting the extra sign-extension
+** bytes if necessary (by default they would be zeros).
+*/
+static void packint (luaL_Buffer_53 *b, lua_Unsigned n,
+                     int islittle, int size, int neg) {
+  char *buff = luaL_prepbuffsize_53(b, size);
+  int i;
+  buff[islittle ? 0 : size - 1] = (char)(n & MC);  /* first byte */
+  for (i = 1; i < size; i++) {
+    n >>= NB;
+    buff[islittle ? i : size - 1 - i] = (char)(n & MC);
+  }
+  if (neg && size > SZINT) {  /* negative number need sign extension? */
+    for (i = SZINT; i < size; i++)  /* correct extra bytes */
+      buff[islittle ? i : size - 1 - i] = (char)MC;
+  }
+  luaL_addsize_53(b, size);  /* add result to buffer */
+}
+
+
+/*
+** Copy 'size' bytes from 'src' to 'dest', correcting endianness if
+** given 'islittle' is different from native endianness.
+*/
+static void copywithendian (volatile char *dest, volatile const char *src,
+                            int size, int islittle) {
+  if (islittle == nativeendian.little) {
+    while (size-- != 0)
+      *(dest++) = *(src++);
+  }
+  else {
+    dest += size - 1;
+    while (size-- != 0)
+      *(dest--) = *(src++);
+  }
+}
+
+
+void lua53_str_pack (lua_State *L, const char *fmt, int startidx, luaL_Buffer_53 *b) {
+  Header h;
+  int arg = startidx - 1;  /* current argument to pack */
+  size_t totalsize = 0;  /* accumulate total size of result */
+  initheader(L, &h);
+  lua_pushnil(L);  /* mark to separate arguments from string buffer */
+  luaL_buffinit_53(L, b);
+  while (*fmt != '\0') {
+    int size, ntoalign;
+    KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
+    totalsize += ntoalign + size;
+    while (ntoalign-- > 0)
+     luaL_addchar_53(b, LUAL_PACKPADBYTE);  /* fill alignment */
+    arg++;
+    switch (opt) {
+      case Kint: {  /* signed integers */
+        lua_Integer n = luaL_checkinteger(L, arg);
+        if (size < SZINT) {  /* need overflow check? */
+          lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1);
+          luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow");
+        }
+        packint(b, (lua_Unsigned)n, h.islittle, size, (n < 0));
+        break;
+      }
+      case Kuint: {  /* unsigned integers */
+        lua_Integer n = luaL_checkinteger(L, arg);
+        if (size < SZINT)  /* need overflow check? */
+          luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)),
+                           arg, "unsigned overflow");
+        packint(b, (lua_Unsigned)n, h.islittle, size, 0);
+        break;
+      }
+      case Kfloat: {  /* floating-point options */
+        volatile Ftypes u;
+        char *buff = luaL_prepbuffsize_53(b, size);
+        lua_Number n = luaL_checknumber(L, arg);  /* get argument */
+        if (size == sizeof(u.f)) u.f = (float)n;  /* copy it into 'u' */
+        else if (size == sizeof(u.d)) u.d = (double)n;
+        else u.n = n;
+        /* move 'u' to final result, correcting endianness if needed */
+        copywithendian(buff, u.buff, size, h.islittle);
+        luaL_addsize_53(b, size);
+        break;
+      }
+      case Kchar: {  /* fixed-size string */
+        size_t len;
+        const char *s = luaL_checklstring(L, arg, &len);
+        luaL_argcheck(L, len <= (size_t)size, arg,
+                         "string longer than given size");
+        luaL_addlstring_53(b, s, len);  /* add string */
+        while (len++ < (size_t)size)  /* pad extra space */
+          luaL_addchar_53(b, LUAL_PACKPADBYTE);
+        break;
+      }
+      case Kstring: {  /* strings with length count */
+        size_t len;
+        const char *s = luaL_checklstring(L, arg, &len);
+        luaL_argcheck(L, size >= (int)sizeof(size_t) ||
+                         len < ((size_t)1 << (size * NB)),
+                         arg, "string length does not fit in given size");
+        packint(b, (lua_Unsigned)len, h.islittle, size, 0);  /* pack length */
+        luaL_addlstring_53(b, s, len);
+        totalsize += len;
+        break;
+      }
+      case Kzstr: {  /* zero-terminated string */
+        size_t len;
+        const char *s = luaL_checklstring(L, arg, &len);
+        luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros");
+        luaL_addlstring_53(b, s, len);
+        luaL_addchar_53(b, '\0');  /* add zero at the end */
+        totalsize += len + 1;
+        break;
+      }
+      case Kpadding: luaL_addchar_53(b, LUAL_PACKPADBYTE);  /* FALLTHROUGH */
+      case Kpaddalign: case Knop:
+        arg--;  /* undo increment */
+        break;
+    }
+  }
+}
+
+
+int lua53_str_packsize (lua_State *L) {
+  Header h;
+  const char *fmt = luaL_checkstring(L, 1);  /* format string */
+  size_t totalsize = 0;  /* accumulate total size of result */
+  initheader(L, &h);
+  while (*fmt != '\0') {
+    int size, ntoalign;
+    KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
+    size += ntoalign;  /* total space used by option */
+    luaL_argcheck(L, totalsize <= MAXSIZE - size, 1,
+                     "format result too large");
+    totalsize += size;
+    switch (opt) {
+      case Kstring:  /* strings with length count */
+      case Kzstr:    /* zero-terminated string */
+        luaL_argerror(L, 1, "variable-length format");
+        /* call never return, but to avoid warnings: *//* FALLTHROUGH */
+      default:  break;
+    }
+  }
+  lua_pushinteger(L, (lua_Integer)totalsize);
+  return 1;
+}
+
+
+/*
+** Unpack an integer with 'size' bytes and 'islittle' endianness.
+** If size is smaller than the size of a Lua integer and integer
+** is signed, must do sign extension (propagating the sign to the
+** higher bits); if size is larger than the size of a Lua integer,
+** it must check the unread bytes to see whether they do not cause an
+** overflow.
+*/
+static lua_Integer unpackint (lua_State *L, const char *str,
+                              int islittle, int size, int issigned) {
+  lua_Unsigned res = 0;
+  int i;
+  int limit = (size  <= SZINT) ? size : SZINT;
+  for (i = limit - 1; i >= 0; i--) {
+    res <<= NB;
+    res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i];
+  }
+  if (size < SZINT) {  /* real size smaller than lua_Integer? */
+    if (issigned) {  /* needs sign extension? */
+      lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1);
+      res = ((res ^ mask) - mask);  /* do sign extension */
+    }
+  }
+  else if (size > SZINT) {  /* must check unread bytes */
+    int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC;
+    for (i = limit; i < size; i++) {
+      if ((unsigned char)str[islittle ? i : size - 1 - i] != mask)
+        luaL_error(L, "%d-byte integer does not fit into Lua Integer", size);
+    }
+  }
+  return (lua_Integer)res;
+}
+
+
+int lua53_str_unpack (lua_State *L, const char *fmt, const char *data, size_t ld, int dataidx, int posidx) {
+  Header h;
+  size_t pos = (size_t)posrelat(luaL_optinteger(L, posidx, 1), ld) - 1;
+  int n = 0;  /* number of results */
+  luaL_argcheck(L, pos <= ld, posidx, "initial position out of string");
+  initheader(L, &h);
+  while (*fmt != '\0') {
+    int size, ntoalign;
+    KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
+    if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld)
+      luaL_argerror(L, dataidx, "data string too short");
+    pos += ntoalign;  /* skip alignment */
+    /* stack space for item + next position */
+    luaL_checkstack(L, dataidx, "too many results");
+    n++;
+    switch (opt) {
+      case Kint:
+      case Kuint: {
+        lua_Integer res = unpackint(L, data + pos, h.islittle, size,
+                                       (opt == Kint));
+        lua_pushinteger(L, res);
+        break;
+      }
+      case Kfloat: {
+        volatile Ftypes u;
+        lua_Number num;
+        copywithendian(u.buff, data + pos, size, h.islittle);
+        if (size == sizeof(u.f)) num = (lua_Number)u.f;
+        else if (size == sizeof(u.d)) num = (lua_Number)u.d;
+        else num = u.n;
+        lua_pushnumber(L, num);
+        break;
+      }
+      case Kchar: {
+        lua_pushlstring(L, data + pos, size);
+        break;
+      }
+      case Kstring: {
+        size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
+        luaL_argcheck(L, pos + len + size <= ld, dataidx, "data string too short");
+        lua_pushlstring(L, data + pos + size, len);
+        pos += len;  /* skip string */
+        break;
+      }
+      case Kzstr: {
+        size_t len = (int)strlen(data + pos);
+        lua_pushlstring(L, data + pos, len);
+        pos += len + 1;  /* skip string plus final '\0' */
+        break;
+      }
+      case Kpaddalign: case Kpadding: case Knop:
+        n--;  /* undo increment */
+        break;
+    }
+    pos += size;
+  }
+  lua_pushinteger(L, pos + 1);  /* next position */
+  return n + 1;
+}
+
+/* }====================================================== */
+

+ 30 - 0
src/libraries/lua53/lstrlib.h

@@ -0,0 +1,30 @@
+
+#ifndef LUA53_LSTRLIB_H
+#define LUA53_LSTRLIB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lua.h"
+
+typedef struct luaL_Buffer_53 {
+	luaL_Buffer b; /* make incorrect code crash! */
+	char *ptr;
+	size_t nelems;
+	size_t capacity;
+	lua_State *L2;
+} luaL_Buffer_53;
+
+void lua53_pushresult (luaL_Buffer_53 *B);
+void lua53_cleanupbuffer (luaL_Buffer_53 *B);
+
+void lua53_str_pack (lua_State *L, const char *fmt, int startidx, luaL_Buffer_53 *b);
+int lua53_str_packsize (lua_State *L);
+int lua53_str_unpack (lua_State *L, const char *fmt, const char *data, size_t ld, int dataidx, int posidx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LUA53_LSTRLIB_H */

+ 0 - 0
src/libraries/luautf8/lutf8lib.c → src/libraries/lua53/lutf8lib.c


+ 3 - 3
src/libraries/luautf8/lutf8lib.h → src/libraries/lua53/lutf8lib.h

@@ -1,6 +1,6 @@
 
-#ifndef LUAUTF8_LUTF8LIB_H
-#define LUAUTF8_LUTF8LIB_H
+#ifndef LUA53_LUTF8LIB_H
+#define LUA53_LUTF8LIB_H
 
 #ifdef __cplusplus
 extern "C" {
@@ -14,4 +14,4 @@ LUALIB_API int luaopen_luautf8(lua_State *L);
 }
 #endif
 
-#endif /* LOVE_LUAUTF8_LUTF8LIB_H */
+#endif /* LUA53_LUTF8LIB_H */

+ 90 - 0
src/modules/data/ByteData.cpp

@@ -0,0 +1,90 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#include "ByteData.h"
+#include "common/Exception.h"
+#include "common/int.h"
+
+#include <string.h>
+
+namespace love
+{
+namespace data
+{
+
+love::Type ByteData::type("ByteData", &Data::type);
+
+ByteData::ByteData(size_t size)
+	: size(size)
+{
+	create();
+	memset(data, 0, size);
+}
+
+ByteData::ByteData(const void *d, size_t size)
+	: size(size)
+{
+	create();
+	memcpy(data, d, size);
+}
+
+ByteData::ByteData(const ByteData &d)
+	: size(d.size)
+{
+	create();
+}
+
+ByteData::~ByteData()
+{
+	delete[] data;
+}
+
+void ByteData::create()
+{
+	if (size == 0)
+		throw love::Exception("ByteData size must be greater than 0.");
+
+	try
+	{
+		data = new char[size];
+	}
+	catch (std::exception &)
+	{
+		throw love::Exception("Out of memory.");
+	}
+}
+
+ByteData *ByteData::clone() const
+{
+	return new ByteData(*this);
+}
+
+void *ByteData::getData() const
+{
+	return data;
+}
+
+size_t ByteData::getSize() const
+{
+	return size;
+}
+
+} // data
+} // love

+ 58 - 0
src/modules/data/ByteData.h

@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#pragma once
+
+#include "common/Data.h"
+
+#include <stddef.h>
+
+namespace love
+{
+namespace data
+{
+
+class ByteData : public love::Data
+{
+public:
+
+	static love::Type type;
+
+	ByteData(size_t size);
+	ByteData(const void *d, size_t size);
+	ByteData(const ByteData &d);
+	virtual ~ByteData();
+
+	// Implements Data.
+	ByteData *clone() const override;
+	void *getData() const override;
+	size_t getSize() const override;
+
+private:
+
+	void create();
+
+	char *data;
+	size_t size;
+
+}; // ByteData
+
+} // data
+} // love

+ 2 - 2
src/modules/math/CompressedData.cpp → src/modules/data/CompressedData.cpp

@@ -23,7 +23,7 @@
 
 namespace love
 {
-namespace math
+namespace data
 {
 
 love::Type CompressedData::type("CompressedData", &Data::type);
@@ -99,5 +99,5 @@ size_t CompressedData::getSize() const
 	return dataSize;
 }
 
-} // math
+} // data
 } // love

+ 4 - 7
src/modules/math/CompressedData.h → src/modules/data/CompressedData.h

@@ -18,8 +18,7 @@
  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
-#ifndef LOVE_MATH_COMPRESSED_DATA_H
-#define LOVE_MATH_COMPRESSED_DATA_H
+#pragma once
 
 // LOVE
 #include "common/Data.h"
@@ -27,11 +26,11 @@
 
 namespace love
 {
-namespace math
+namespace data
 {
 
 /**
- * Stores byte data compressed via Math::compress.
+ * Stores byte data compressed via DataModule::compress.
  **/
 class CompressedData : public love::Data
 {
@@ -73,7 +72,5 @@ private:
 
 }; // CompressedData
 
-} // math
+} // data
 } // love
-
-#endif // LOVE_MATH_COMPRESSED_DATA_H

+ 5 - 7
src/modules/math/Compressor.cpp → src/modules/data/Compressor.cpp

@@ -23,16 +23,14 @@
 #include "common/config.h"
 #include "common/int.h"
 
-// LZ4
 #include "libraries/lz4/lz4.h"
 #include "libraries/lz4/lz4hc.h"
 
-// zlib
 #include <zlib.h>
 
 namespace love
 {
-namespace math
+namespace data
 {
 
 class LZ4Compressor : public Compressor
@@ -383,12 +381,12 @@ bool Compressor::getConstant(Format in, const char *&out)
 
 StringMap<Compressor::Format, Compressor::FORMAT_MAX_ENUM>::Entry Compressor::formatEntries[] =
 {
-	{"lz4",  FORMAT_LZ4},
-	{"zlib", FORMAT_ZLIB},
-	{"gzip", FORMAT_GZIP},
+	{ "lz4",  FORMAT_LZ4  },
+	{ "zlib", FORMAT_ZLIB },
+	{ "gzip", FORMAT_GZIP },
 };
 
 StringMap<Compressor::Format, Compressor::FORMAT_MAX_ENUM> Compressor::formatNames(Compressor::formatEntries, sizeof(Compressor::formatEntries));
 
-} // math
+} // data
 } // love

+ 3 - 6
src/modules/math/Compressor.h → src/modules/data/Compressor.h

@@ -18,15 +18,14 @@
  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
-#ifndef LOVE_MATH_COMPRESSOR_H
-#define LOVE_MATH_COMPRESSOR_H
+#pragma once
 
 // LOVE
 #include "common/StringMap.h"
 
 namespace love
 {
-namespace math
+namespace data
 {
 
 /**
@@ -100,7 +99,5 @@ private:
 
 }; // Compressor
 
-} // math
+} // data
 } // love
-
-#endif // LOVE_MATH_COMPRESSOR_H

+ 267 - 0
src/modules/data/DataModule.cpp

@@ -0,0 +1,267 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+// LOVE
+#include "DataModule.h"
+#include "common/b64.h"
+#include "common/int.h"
+#include "common/StringMap.h"
+
+// STL
+#include <cmath>
+#include <list>
+#include <iostream>
+
+namespace
+{
+
+static const char hexchars[] = "0123456789abcdef";
+
+char *bytesToHex(const love::uint8 *src, size_t srclen, size_t &dstlen)
+{
+	dstlen = srclen * 2;
+
+	if (dstlen == 0)
+		return nullptr;
+
+	char *dst = nullptr;
+	try
+	{
+		dst = new char[dstlen + 1];
+	}
+	catch (std::exception &)
+	{
+		throw love::Exception("Out of memory.");
+	}
+
+	for (size_t i = 0; i < srclen; i++)
+	{
+		love::uint8 b = src[i];
+		dst[i * 2 + 0] = hexchars[b >> 4];
+		dst[i * 2 + 1] = hexchars[b & 0xF];
+	}
+
+	dst[dstlen] = '\0';
+	return dst;
+}
+
+love::uint8 nibble(char c)
+{
+	if (c >= '0' && c <= '9')
+		return (love::uint8) (c - '0');
+
+	if (c >= 'A' && c <= 'F')
+		return (love::uint8) (c - 'A' + 0x0a);
+
+	if (c >= 'a' && c <= 'f')
+		return (love::uint8) (c - 'a' + 0x0a);
+
+	return 0;
+}
+
+love::uint8 *hexToBytes(const char *src, size_t srclen, size_t &dstlen)
+{
+	if (srclen >= 2 && src[0] == '0' && (src[1] == 'x' || src[1] == 'X'))
+	{
+		src += 2;
+		srclen -= 2;
+	}
+
+	dstlen = (srclen + 1) / 2;
+
+	if (dstlen == 0)
+		return nullptr;
+
+	love::uint8 *dst = nullptr;
+	try
+	{
+		dst = new love::uint8[dstlen];
+	}
+	catch (std::exception &)
+	{
+		throw love::Exception("Out of memory.");
+	}
+
+	for (size_t i = 0; i < dstlen; i++)
+	{
+		dst[i] = nibble(src[i * 2]) << 4;
+
+		if (i * 2 + 1 < srclen)
+			dst[i] |= nibble(src[i * 2 + 1]);
+	}
+
+	return dst;
+}
+
+} // anonymous namespace
+
+namespace love
+{
+namespace data
+{
+
+CompressedData *compress(Compressor::Format format, love::Data *rawdata, int level)
+{
+	return compress(format, (const char *) rawdata->getData(), rawdata->getSize(), level);
+}
+
+CompressedData *compress(Compressor::Format format, const char *rawbytes, size_t rawsize, int level)
+{
+	Compressor *compressor = Compressor::getCompressor(format);
+
+	if (compressor == nullptr)
+		throw love::Exception("Invalid compression format.");
+
+	size_t compressedsize = 0;
+	char *cbytes = compressor->compress(format, rawbytes, rawsize, level, compressedsize);
+
+	CompressedData *data = nullptr;
+
+	try
+	{
+		data = new CompressedData(format, cbytes, compressedsize, rawsize, true);
+	}
+	catch (love::Exception &)
+	{
+		delete[] cbytes;
+		throw;
+	}
+
+	return data;
+}
+
+char *decompress(CompressedData *data, size_t &decompressedsize)
+{
+	size_t rawsize = data->getDecompressedSize();
+
+	char *rawbytes = decompress(data->getFormat(), (const char *) data->getData(),
+	                            data->getSize(), rawsize);
+
+	decompressedsize = rawsize;
+	return rawbytes;
+}
+
+char *decompress(Compressor::Format format, const char *cbytes, size_t compressedsize, size_t &rawsize)
+{
+	Compressor *compressor = Compressor::getCompressor(format);
+
+	if (compressor == nullptr)
+		throw love::Exception("Invalid compression format.");
+
+	return compressor->decompress(format, cbytes, compressedsize, rawsize);
+}
+
+char *encode(EncodeFormat format, const char *src, size_t srclen, size_t &dstlen, size_t linelen)
+{
+	switch (format)
+	{
+	case ENCODE_BASE64:
+	default:
+		return b64_encode(src, srclen, linelen, dstlen);
+	case ENCODE_HEX:
+		return bytesToHex((const uint8 *) src, srclen, dstlen);
+	}
+}
+
+char *decode(EncodeFormat format, const char *src, size_t srclen, size_t &dstlen)
+{
+	switch (format)
+	{
+	case ENCODE_BASE64:
+	default:
+		return b64_decode(src, srclen, dstlen);
+	case ENCODE_HEX:
+		return (char *) hexToBytes(src, srclen, dstlen);
+	}
+}
+
+std::string hash(HashFunction::Function function, Data *input)
+{
+	return hash(function, (const char*) input->getData(), input->getSize());
+}
+
+std::string hash(HashFunction::Function function, const char *input, uint64_t size)
+{
+	HashFunction::Value output;
+	hash(function, input, size, output);
+	return std::string(output.data, output.size);
+}
+
+void hash(HashFunction::Function function, Data *input, HashFunction::Value &output)
+{
+	hash(function, (const char*) input->getData(), input->getSize(), output);
+}
+
+void hash(HashFunction::Function function, const char *input, uint64_t size, HashFunction::Value &output)
+{
+	HashFunction *hashfunction = HashFunction::getHashFunction(function);
+	if (hashfunction == nullptr)
+		throw love::Exception("Invalid hash function.");
+
+	hashfunction->hash(function, input, size, output);
+}
+
+DataModule DataModule::instance;
+
+DataModule::DataModule()
+{
+	// prevent the runtime from free()-ing this
+	retain();
+}
+
+DataModule::~DataModule()
+{
+}
+
+DataView *DataModule::newDataView(Data *data, size_t offset, size_t size)
+{
+	return new DataView(data, offset, size);
+}
+
+ByteData *DataModule::newByteData(size_t size)
+{
+	return new ByteData(size);
+}
+
+ByteData *DataModule::newByteData(const void *d, size_t size)
+{
+	return new ByteData(d, size);
+}
+
+static StringMap<EncodeFormat, ENCODE_MAX_ENUM>::Entry encoderEntries[] =
+{
+	{ "base64", ENCODE_BASE64 },
+	{ "hex",    ENCODE_HEX    },
+};
+
+static StringMap<EncodeFormat, ENCODE_MAX_ENUM> encoders(encoderEntries, sizeof(encoderEntries));
+
+bool getConstant(const char *in, EncodeFormat &out)
+{
+	return encoders.find(in, out);
+}
+
+bool getConstant(EncodeFormat in, const char *&out)
+{
+	return encoders.find(in, out);
+}
+
+} // data
+} // love

+ 124 - 0
src/modules/data/DataModule.h

@@ -0,0 +1,124 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#pragma once
+
+#include "CompressedData.h"
+#include "Compressor.h"
+#include "HashFunction.h"
+#include "DataView.h"
+#include "ByteData.h"
+
+// LOVE
+#include "common/Module.h"
+#include "common/int.h"
+
+namespace love
+{
+namespace data
+{
+
+enum EncodeFormat
+{
+	ENCODE_BASE64,
+	ENCODE_HEX,
+	ENCODE_MAX_ENUM
+};
+
+/**
+ * Compresses a block of memory using the given compression format.
+ *
+ * @param format The compression format to use.
+ * @param rawdata The data to compress.
+ * @param level The amount of compression to apply (between 0 and 9.)
+ *              A value of -1 indicates the default amount of compression.
+ *              Specific formats may not use every level.
+ * @return The newly compressed data.
+ **/
+CompressedData *compress(Compressor::Format format, Data *rawdata, int level = -1);
+CompressedData *compress(Compressor::Format format, const char *rawbytes, size_t rawsize, int level = -1);
+
+/**
+ * Decompresses existing compressed data into raw bytes.
+ *
+ * @param[in] data The compressed data to decompress.
+ * @param[out] decompressedsize The size in bytes of the decompressed data.
+ * @return The newly decompressed data (allocated with new[]).
+ **/
+char *decompress(CompressedData *data, size_t &decompressedsize);
+
+/**
+ * Decompresses existing compressed data into raw bytes.
+ *
+ * @param[in] format The compression format the data is in.
+ * @param[in] cbytes The compressed data to decompress.
+ * @param[in] compressedsize The size in bytes of the compressed data.
+ * @param[in,out] rawsize On input, the size in bytes of the original
+ *               uncompressed data, or 0 if unknown. On return, the size in
+ *               bytes of the newly decompressed data.
+ * @return The newly decompressed data (allocated with new[]).
+ **/
+char *decompress(Compressor::Format format, const char *cbytes, size_t compressedsize, size_t &rawsize);
+
+char *encode(EncodeFormat format, const char *src, size_t srclen, size_t &dstlen, size_t linelen = 0);
+char *decode(EncodeFormat format, const char *src, size_t srclen, size_t &dstlen);
+
+/**
+ * Hash the input, producing an set of bytes as output.
+ *
+ * @param[in] function The selected hash function.
+ * @param[in] input The input data to hash.
+ * @return An std::string of bytes, representing the result of the hash
+ *         function.
+ **/
+std::string hash(HashFunction::Function function, Data *input);
+std::string hash(HashFunction::Function function, const char *input, uint64_t size);
+void hash(HashFunction::Function function, Data *input, HashFunction::Value &output);
+void hash(HashFunction::Function function, const char *input, uint64_t size, HashFunction::Value &output);
+
+
+bool getConstant(const char *in, EncodeFormat &out);
+bool getConstant(EncodeFormat in, const char *&out);
+
+
+class DataModule : public Module
+{
+public:
+
+	virtual ~DataModule();
+
+	// Implements Module.
+	ModuleType getModuleType() const override { return M_DATA; }
+	const char *getName() const override { return "love.data"; }
+
+	DataView *newDataView(Data *data, size_t offset, size_t size);
+	ByteData *newByteData(size_t size);
+	ByteData *newByteData(const void *d, size_t size);
+
+	static DataModule instance;
+
+private:
+
+	DataModule();
+
+}; // DataModule
+
+} // data
+} // love

+ 71 - 0
src/modules/data/DataView.cpp

@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#include "DataView.h"
+#include "common/Exception.h"
+#include "common/int.h"
+
+namespace love
+{
+namespace data
+{
+
+love::Type DataView::type("DataView", &Data::type);
+
+DataView::DataView(Data *data, size_t offset, size_t size)
+	: data(data)
+	, offset(offset)
+	, size(size)
+{
+	if (offset >= data->getSize() || size > data->getSize() || offset > data->getSize() - size)
+		throw love::Exception("Offset and size of Data View must fit within the original Data's size.");
+
+	if (size == 0)
+		throw love::Exception("DataView size must be greater than 0.");
+}
+
+DataView::DataView(const DataView &d)
+	: data(d.data)
+	, offset(d.offset)
+	, size(d.size)
+{
+}
+
+DataView::~DataView()
+{
+}
+
+DataView *DataView::clone() const
+{
+	return new DataView(*this);
+}
+
+void *DataView::getData() const
+{
+	return (uint8 *) data->getData() + offset;
+}
+
+size_t DataView::getSize() const
+{
+	return size;
+}
+
+} // data
+} // love

+ 57 - 0
src/modules/data/DataView.h

@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#pragma once
+
+#include "common/Data.h"
+
+namespace love
+{
+namespace data
+{
+
+/**
+ * Contains a reference to a subsection of an existing Data object.
+ **/
+class DataView : public love::Data
+{
+public:
+
+	static love::Type type;
+
+	DataView(Data *data, size_t offset, size_t size);
+	DataView(const DataView &d);
+	virtual ~DataView();
+
+	// Implements Data.
+	DataView *clone() const override;
+	void *getData() const override;
+	size_t getSize() const override;
+
+private:
+
+	StrongRef<Data> data;
+	size_t offset;
+	size_t size;
+
+}; // DataView
+
+} // data
+} // love

+ 30 - 34
src/modules/math/HashFunction.cpp → src/modules/data/HashFunction.cpp

@@ -27,7 +27,7 @@
 
 namespace love
 {
-namespace math
+namespace data
 {
 
 namespace
@@ -69,7 +69,7 @@ public:
 		return function == FUNCTION_MD5;
 	}
 
-	std::string hash(Function function, const char *input, uint64 length) const override
+	void hash(Function function, const char *input, uint64 length, Value &output) const override
 	{
 		if (function != FUNCTION_MD5)
 			throw love::Exception("Hash function not supported by MD5 implementation");
@@ -141,12 +141,11 @@ public:
 
 		delete[] padded;
 
-		std::string hash(16, ' ');
-		hash.replace( 0, 4, (const char*) &a0, 4);
-		hash.replace( 4, 4, (const char*) &b0, 4);
-		hash.replace( 8, 4, (const char*) &c0, 4);
-		hash.replace(12, 4, (const char*) &d0, 4);
-		return hash;
+		memcpy(&output.data[ 0], &a0, 4);
+		memcpy(&output.data[ 4], &b0, 4);
+		memcpy(&output.data[ 8], &c0, 4);
+		memcpy(&output.data[12], &d0, 4);
+		output.size = 16;
 	}
 } md5;
 
@@ -189,7 +188,7 @@ public:
 		return function == FUNCTION_SHA1;
 	}
 
-	std::string hash(Function function, const char *input, uint64 length) const override
+	void hash(Function function, const char *input, uint64 length, Value &output) const override
 	{
 		if (function != FUNCTION_SHA1)
 			throw love::Exception("Hash function not supported by SHA1 implementation");
@@ -266,16 +265,15 @@ public:
 
 		delete[] padded;
 
-		std::string hash(20, ' ');
 		for (int i = 0; i < 20; i += 4)
 		{
-			hash[i+0] = (intermediate[i/4] >> 24) & 0xFF;
-			hash[i+1] = (intermediate[i/4] >> 16) & 0xFF;
-			hash[i+2] = (intermediate[i/4] >>  8) & 0xFF;
-			hash[i+3] = (intermediate[i/4] >>  0) & 0xFF;
+			output.data[i+0] = (intermediate[i/4] >> 24) & 0xFF;
+			output.data[i+1] = (intermediate[i/4] >> 16) & 0xFF;
+			output.data[i+2] = (intermediate[i/4] >>  8) & 0xFF;
+			output.data[i+3] = (intermediate[i/4] >>  0) & 0xFF;
 		}
 
-		return hash;
+		output.size = 20;
 	}
 } sha1;
 
@@ -296,7 +294,7 @@ public:
 		return function == FUNCTION_SHA224 || function == FUNCTION_SHA256;
 	}
 
-	std::string hash(Function function, const char *input, uint64 length) const override
+	void hash(Function function, const char *input, uint64 length, Value &output) const override
 	{
 		if (!isSupported(function))
 			throw love::Exception("Hash function not supported by SHA-224/SHA-256 implementation");
@@ -387,16 +385,15 @@ public:
 		if (function == FUNCTION_SHA224)
 			hashlength = 28;
 
-		std::string hash(hashlength, ' ');
 		for (int i = 0; i < hashlength; i += 4)
 		{
-			hash[i+0] = (intermediate[i/4] >> 24) & 0xFF;
-			hash[i+1] = (intermediate[i/4] >> 16) & 0xFF;
-			hash[i+2] = (intermediate[i/4] >>  8) & 0xFF;
-			hash[i+3] = (intermediate[i/4] >>  0) & 0xFF;
+			output.data[i+0] = (intermediate[i/4] >> 24) & 0xFF;
+			output.data[i+1] = (intermediate[i/4] >> 16) & 0xFF;
+			output.data[i+2] = (intermediate[i/4] >>  8) & 0xFF;
+			output.data[i+3] = (intermediate[i/4] >>  0) & 0xFF;
 		}
 
-		return hash;
+		output.size = hashlength;
 	}
 } sha256;
 
@@ -446,7 +443,7 @@ public:
 		return function == FUNCTION_SHA384 || function == FUNCTION_SHA512;
 	}
 
-	std::string hash(Function function, const char *input, uint64 length) const override
+	void hash(Function function, const char *input, uint64 length, Value &output) const override
 	{
 		if (!isSupported(function))
 			throw love::Exception("Hash function not supported by SHA-384/SHA-512 implementation");
@@ -541,20 +538,19 @@ public:
 		if (function == FUNCTION_SHA384)
 			hashlength = 48;
 
-		std::string hash(hashlength, ' ');
 		for (int i = 0; i < hashlength; i += 8)
 		{
-			hash[i+0] = (intermediates[i/8] >> 56) & 0xFF;
-			hash[i+1] = (intermediates[i/8] >> 48) & 0xFF;
-			hash[i+2] = (intermediates[i/8] >> 40) & 0xFF;
-			hash[i+3] = (intermediates[i/8] >> 32) & 0xFF;
-			hash[i+4] = (intermediates[i/8] >> 24) & 0xFF;
-			hash[i+5] = (intermediates[i/8] >> 16) & 0xFF;
-			hash[i+6] = (intermediates[i/8] >>  8) & 0xFF;
-			hash[i+7] = (intermediates[i/8] >>  0) & 0xFF;
+			output.data[i+0] = (intermediates[i/8] >> 56) & 0xFF;
+			output.data[i+1] = (intermediates[i/8] >> 48) & 0xFF;
+			output.data[i+2] = (intermediates[i/8] >> 40) & 0xFF;
+			output.data[i+3] = (intermediates[i/8] >> 32) & 0xFF;
+			output.data[i+4] = (intermediates[i/8] >> 24) & 0xFF;
+			output.data[i+5] = (intermediates[i/8] >> 16) & 0xFF;
+			output.data[i+6] = (intermediates[i/8] >>  8) & 0xFF;
+			output.data[i+7] = (intermediates[i/8] >>  0) & 0xFF;
 		}
 
-		return hash;
+		output.size = hashlength;
 	}
 } sha512;
 
@@ -636,5 +632,5 @@ StringMap<HashFunction::Function, HashFunction::FUNCTION_MAX_ENUM>::Entry HashFu
 
 StringMap<HashFunction::Function, HashFunction::FUNCTION_MAX_ENUM> HashFunction::functionNames(HashFunction::functionEntries, sizeof(HashFunction::functionEntries));
 
-} // math
+} // data
 } // love

+ 15 - 8
src/modules/math/HashFunction.h → src/modules/data/HashFunction.h

@@ -18,8 +18,7 @@
  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
-#ifndef LOVE_MATH_HASH_FUNCTION_H
-#define LOVE_MATH_HASH_FUNCTION_H
+#pragma once
 
 // LOVE
 #include "common/Data.h"
@@ -28,12 +27,13 @@
 
 namespace love
 {
-namespace math
+namespace data
 {
 
 class HashFunction
 {
 public:
+
 	enum Function
 	{
 		FUNCTION_MD5,
@@ -45,6 +45,12 @@ public:
 		FUNCTION_MAX_ENUM
 	};
 
+	struct Value
+	{
+		char data[64]; // Maximum possible size (SHA512).
+		size_t size;
+	};
+
 	/**
 	 * Get a HashFunction instance for the given function.
 	 *
@@ -62,9 +68,9 @@ public:
 	 * @param[in] function The selected hash function.
 	 * @param[in] input The input data to hash.
 	 * @param[in] length The length of the input data.
-	 * @return A string of bytes, representing the result of the hash function.
+	 * @param[out] output The result of the hash function.
 	 **/
-	virtual std::string hash(Function function, const char *input, uint64 length) const = 0;
+	virtual void hash(Function function, const char *input, uint64 length, Value &output) const = 0;
 
 	/**
 	 * @param[in] function The requested hash function.
@@ -76,14 +82,15 @@ public:
 	static bool getConstant(const Function &in, const char *&out);
 
 protected:
+
 	HashFunction() {}
 
 private:
+
 	static StringMap<Function, FUNCTION_MAX_ENUM>::Entry functionEntries[];
 	static StringMap<Function, FUNCTION_MAX_ENUM> functionNames;
+
 }; // HashFunction
 
-} // math
+} // data
 } // love
-
-#endif // LOVE_MATH_HASH_FUNCTION_H

+ 46 - 0
src/modules/data/wrap_ByteData.cpp

@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#include "wrap_ByteData.h"
+#include "wrap_Data.h"
+
+namespace love
+{
+namespace data
+{
+
+ByteData *luax_checkbytedata(lua_State *L, int idx)
+{
+	return luax_checktype<ByteData>(L, idx);
+}
+
+static const luaL_Reg w_ByteData_functions[] =
+{
+	{ 0, 0 }
+};
+
+int luaopen_bytedata(lua_State *L)
+{
+	luax_register_type(L, &ByteData::type, w_Data_functions, w_ByteData_functions, nullptr);
+	return 0;
+}
+
+} // data
+} // love

+ 36 - 0
src/modules/data/wrap_ByteData.h

@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#pragma once
+
+// LOVE
+#include "common/runtime.h"
+#include "ByteData.h"
+
+namespace love
+{
+namespace data
+{
+
+ByteData *luax_checkbytedata(lua_State *L, int idx);
+int luaopen_bytedata(lua_State *L);
+
+} // data
+} // love

+ 3 - 3
src/modules/math/wrap_CompressedData.cpp → src/modules/data/wrap_CompressedData.cpp

@@ -20,11 +20,11 @@
 
 // LOVE
 #include "wrap_CompressedData.h"
-#include "common/wrap_Data.h"
+#include "wrap_Data.h"
 
 namespace love
 {
-namespace math
+namespace data
 {
 
 CompressedData *luax_checkcompresseddata(lua_State *L, int idx)
@@ -66,5 +66,5 @@ extern "C" int luaopen_compresseddata(lua_State *L)
 	return luax_register_type(L, &CompressedData::type, w_Data_functions, w_CompressedData_functions, nullptr);
 }
 
-} // math
+} // data
 } // love

+ 3 - 6
src/modules/math/wrap_CompressedData.h → src/modules/data/wrap_CompressedData.h

@@ -18,8 +18,7 @@
  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
-#ifndef LOVE_MATH_WRAP_COMPRESSED_DATA_H
-#define LOVE_MATH_WRAP_COMPRESSED_DATA_H
+#pragma once
 
 // LOVE
 #include "common/runtime.h"
@@ -27,13 +26,11 @@
 
 namespace love
 {
-namespace math
+namespace data
 {
 
 CompressedData *luax_checkcompresseddata(lua_State *L, int idx);
 extern "C" int luaopen_compresseddata(lua_State *L);
 
-} // math
+} // data
 } // love
-
-#endif // LOVE_MATH_WRAP_COMPRESSED_DATA_H

+ 4 - 1
src/common/wrap_Data.cpp → src/modules/data/wrap_Data.cpp

@@ -22,6 +22,8 @@
 
 namespace love
 {
+namespace data
+{
 
 Data *luax_checkdata(lua_State *L, int idx)
 {
@@ -57,10 +59,11 @@ const luaL_Reg w_Data_functions[] =
 	{ 0, 0 }
 };
 
-int w_Data_open(lua_State *L)
+int luaopen_data(lua_State *L)
 {
 	luax_register_type(L, &Data::type, w_Data_functions, nullptr);
 	return 0;
 }
 
+} // data
 } // love

+ 7 - 7
src/common/wrap_Data.h → src/modules/data/wrap_Data.h

@@ -18,20 +18,20 @@
  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
-#ifndef LOVE_WRAP_DATA_H
-#define LOVE_WRAP_DATA_H
+#pragma once
 
 // LOVE
-#include "runtime.h"
-#include "Data.h"
+#include "common/runtime.h"
+#include "common/Data.h"
 
 namespace love
 {
+namespace data
+{
 
 Data *luax_checkdata(lua_State *L, int idx);
-int w_Data_open(lua_State *L);
+int luaopen_data(lua_State *L);
 extern const luaL_Reg w_Data_functions[];
 
+} // data
 } // love
-
-#endif // LOVE_WRAP_DATA_H

+ 357 - 0
src/modules/data/wrap_DataModule.cpp

@@ -0,0 +1,357 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+// LOVE
+#include "wrap_DataModule.h"
+#include "wrap_Data.h"
+#include "wrap_ByteData.h"
+#include "wrap_DataView.h"
+#include "wrap_CompressedData.h"
+#include "DataModule.h"
+#include "common/b64.h"
+
+// Lua 5.3
+#include "libraries/lua53/lstrlib.h"
+
+// C
+#include <cmath>
+#include <iostream>
+#include <algorithm>
+#include <limits>
+
+namespace love
+{
+namespace data
+{
+
+int w_newDataView(lua_State *L)
+{
+	Data *data = luax_checkdata(L, 1);
+
+	lua_Integer offset = luaL_checkinteger(L, 2);
+	lua_Integer size = luaL_checkinteger(L, 3);
+
+	if (offset < 0 || size < 0)
+		return luaL_error(L, "DataView offset and size must not be negative.");
+
+	DataView *d = DataModule::instance.newDataView(data, (size_t) offset, (size_t) size);
+	luax_pushtype(L, d);
+	d->release();
+
+	return 1;
+}
+
+int w_newByteData(lua_State *L)
+{
+	ByteData *d = nullptr;
+
+	if (luax_istype(L, 1, Data::type))
+	{
+		Data *data = luax_checkdata(L, 1);
+
+		if (data->getSize() > std::numeric_limits<lua_Integer>::max())
+			return luaL_error(L, "Data's size is too large!");
+
+		lua_Integer offset = luaL_optinteger(L, 2, 0);
+		if (offset < 0)
+			return luaL_error(L, "Offset argument must not be negative.");
+
+		lua_Integer size = luaL_optinteger(L, 3, data->getSize() - offset);
+		if (size <= 0)
+			return luaL_error(L, "Size argument must be greater than zero.");
+		else if ((size_t)(offset + size) > data->getSize())
+			return luaL_error(L, "Offset and size arguments must fit within the given Data's size.");
+
+		const char *bytes = (const char *) data->getData() + offset;
+		luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData(bytes, (size_t) size); });
+	}
+	else if (lua_type(L, 1) == LUA_TSTRING)
+	{
+		size_t size = 0;
+		const char *data = luaL_checklstring(L, 1, &size);
+		luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData(data, size); });
+	}
+	else
+	{
+		lua_Integer size = luaL_checkinteger(L, 1);
+		if (size <= 0)
+			return luaL_error(L, "Data size must be a positive number.");
+		luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData((size_t) size); });
+	}
+
+	luax_pushtype(L, d);
+	d->release();
+	return 1;
+}
+
+int w_compress(lua_State *L)
+{
+	const char *fstr = luaL_checkstring(L, 1);
+	Compressor::Format format = Compressor::FORMAT_LZ4;
+
+	if (!Compressor::getConstant(fstr, format))
+		return luaL_error(L, "Invalid compressed data format: %s", fstr);
+
+	int level = (int) luaL_optinteger(L, 3, -1);
+
+	CompressedData *cdata = nullptr;
+	if (lua_isstring(L, 2))
+	{
+		size_t rawsize = 0;
+		const char *rawbytes = luaL_checklstring(L, 2, &rawsize);
+		luax_catchexcept(L, [&](){ cdata = compress(format, rawbytes, rawsize, level); });
+	}
+	else
+	{
+		Data *rawdata = luax_checktype<Data>(L, 2);
+		luax_catchexcept(L, [&](){ cdata = compress(format, rawdata, level); });
+	}
+
+	luax_pushtype(L, cdata);
+	cdata->release();
+	return 1;
+}
+
+int w_decompress(lua_State *L)
+{
+	char *rawbytes = nullptr;
+	size_t rawsize = 0;
+
+	if (luax_istype(L, 1, CompressedData::type))
+	{
+		CompressedData *data = luax_checkcompresseddata(L, 1);
+		rawsize = data->getDecompressedSize();
+		luax_catchexcept(L, [&](){ rawbytes = decompress(data, rawsize); });
+	}
+	else
+	{
+		Compressor::Format format = Compressor::FORMAT_LZ4;
+		const char *fstr = luaL_checkstring(L, 1);
+
+		if (!Compressor::getConstant(fstr, format))
+			return luaL_error(L, "Invalid compressed data format: %s", fstr);
+
+		size_t compressedsize = 0;
+		const char *cbytes = nullptr;
+
+		if (luax_istype(L, 2, Data::type))
+		{
+			Data *data = luax_checktype<Data>(L, 2);
+			cbytes = (const char *) data->getData();
+			compressedsize = data->getSize();
+		}
+		else
+			cbytes = luaL_checklstring(L, 2, &compressedsize);
+
+		luax_catchexcept(L, [&](){ rawbytes = decompress(format, cbytes, compressedsize, rawsize); });
+	}
+
+	lua_pushlstring(L, rawbytes, rawsize);
+	delete[] rawbytes;
+
+	return 1;
+}
+
+int w_encode(lua_State *L)
+{
+	const char *formatstr = luaL_checkstring(L, 1);
+	EncodeFormat format;
+	if (!getConstant(formatstr, format))
+		return luaL_error(L, "Invalid encode format: %s", formatstr);
+
+	size_t srclen = 0;
+	const char *src = nullptr;
+
+	if (luax_istype(L, 2, Data::type))
+	{
+		Data *data = luax_totype<Data>(L, 2);
+		src = (const char *) data->getData();
+		srclen = data->getSize();
+	}
+	else
+		src = luaL_checklstring(L, 2, &srclen);
+
+	size_t linelen = (size_t) luaL_optinteger(L, 3, 0);
+
+	size_t dstlen = 0;
+	char *dst = nullptr;
+	luax_catchexcept(L, [&](){ dst = encode(format, src, srclen, dstlen, linelen); });
+
+	if (dst != nullptr)
+		lua_pushlstring(L, dst, dstlen);
+	else
+		lua_pushstring(L, "");
+
+	delete[] dst;
+	return 1;
+}
+
+int w_decode(lua_State *L)
+{
+	const char *formatstr = luaL_checkstring(L, 1);
+	EncodeFormat format;
+	if (!getConstant(formatstr, format))
+		return luaL_error(L, "Invalid decode format: %s", formatstr);
+
+	size_t srclen = 0;
+	const char *src = nullptr;
+
+	if (luax_istype(L, 2, Data::type))
+	{
+		Data *data = luax_totype<Data>(L, 2);
+		src = (const char *) data->getData();
+		srclen = data->getSize();
+	}
+	else
+		src = luaL_checklstring(L, 2, &srclen);
+
+	size_t dstlen = 0;
+	char *dst = nullptr;
+	luax_catchexcept(L, [&](){ dst = decode(format, src, srclen, dstlen); });
+
+	if (dst != nullptr)
+		lua_pushlstring(L, dst, dstlen);
+	else
+		lua_pushstring(L, "");
+
+	delete[] dst;
+	return 1;
+}
+
+int w_hash(lua_State *L)
+{
+	const char *fstr = luaL_checkstring(L, 1);
+	HashFunction::Function function;
+	if (!HashFunction::getConstant(fstr, function))
+		return luaL_error(L, "Invalid hash function: %s", fstr);
+
+	HashFunction::Value hashvalue;
+	if (lua_isstring(L, 2))
+	{
+		size_t rawsize = 0;
+		const char *rawbytes = luaL_checklstring(L, 2, &rawsize);
+		luax_catchexcept(L, [&](){ love::data::hash(function, rawbytes, rawsize, hashvalue); });
+	}
+	else
+	{
+		Data *rawdata = luax_checktype<Data>(L, 2);
+		luax_catchexcept(L, [&](){ love::data::hash(function, rawdata, hashvalue); });
+	}
+
+	lua_pushlstring(L, hashvalue.data, hashvalue.size);
+	return 1;
+}
+
+static int w_pack(lua_State *L, bool data)
+{
+	const char *fmt = luaL_checkstring(L, 1);
+	luaL_Buffer_53 b;
+	lua53_str_pack(L, fmt, 2, &b);
+
+	if (data)
+	{
+		Data *d = nullptr;
+		luax_catchexcept(L, [&]() { d = DataModule::instance.newByteData(b.nelems); });
+		memcpy(d->getData(), b.ptr, d->getSize());
+
+		lua53_cleanupbuffer(&b);
+		luax_pushtype(L, Data::type, d);
+		d->release();
+	}
+	else
+		lua53_pushresult(&b);
+
+	return 1;
+}
+
+int w_packString(lua_State *L)
+{
+	return w_pack(L, false);
+}
+
+int w_packData(lua_State *L)
+{
+	return w_pack(L, true);
+}
+
+int w_unpack(lua_State *L)
+{
+	const char *fmt = luaL_checkstring(L, 1);
+
+	const char *data = nullptr;
+	size_t datasize = 0;
+
+	if (luax_istype(L, 2, Data::type))
+	{
+		Data *d = luax_checkdata(L, 2);
+		data = (const char *) d->getData();
+		datasize = d->getSize();
+	}
+	else
+		data = luaL_checklstring(L, 2, &datasize);
+
+	return lua53_str_unpack(L, fmt, data, datasize, 2, 3);
+}
+
+// List of functions to wrap.
+static const luaL_Reg functions[] =
+{
+	{ "newDataView", w_newDataView },
+	{ "newByteData", w_newByteData },
+	{ "compress", w_compress },
+	{ "decompress", w_decompress },
+	{ "encode", w_encode },
+	{ "decode", w_decode },
+	{ "hash", w_hash },
+
+	{ "packString", w_packString },
+	{ "packData", w_packData },
+	{ "unpack", w_unpack },
+	{ "getPackedSize", lua53_str_packsize },
+
+	{ 0, 0 }
+};
+
+static const lua_CFunction types[] =
+{
+	luaopen_data,
+	luaopen_bytedata,
+	luaopen_dataview,
+	luaopen_compresseddata,
+	nullptr
+};
+
+extern "C" int luaopen_love_data(lua_State *L)
+{
+	DataModule::instance.retain();
+
+	WrappedModule w;
+	w.module = &DataModule::instance;
+	w.name = "data";
+	w.type = &Module::type;
+	w.functions = functions;
+	w.types = types;
+
+	int n = luax_register_module(L, w);
+	return n;
+}
+
+} // data
+} // love

+ 37 - 0
src/modules/data/wrap_DataModule.h

@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#pragma once
+
+// LOVE
+#include "common/config.h"
+#include "common/runtime.h"
+
+namespace love
+{
+namespace data
+{
+
+int w_compress(lua_State *L);
+int w_decompress(lua_State *L);
+extern "C" LOVE_EXPORT int luaopen_love_data(lua_State *L);
+
+} // data
+} // love

+ 46 - 0
src/modules/data/wrap_DataView.cpp

@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#include "wrap_DataView.h"
+#include "wrap_Data.h"
+
+namespace love
+{
+namespace data
+{
+
+DataView *luax_checkdataView(lua_State *L, int idx)
+{
+	return luax_checktype<DataView>(L, idx);
+}
+
+static const luaL_Reg w_DataView_functions[] =
+{
+	{ 0, 0 }
+};
+
+int luaopen_dataview(lua_State *L)
+{
+	luax_register_type(L, &DataView::type, w_Data_functions, w_DataView_functions, nullptr);
+	return 0;
+}
+
+} // data
+} // love

+ 36 - 0
src/modules/data/wrap_DataView.h

@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2006-2017 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#pragma once
+
+// LOVE
+#include "common/runtime.h"
+#include "DataView.h"
+
+namespace love
+{
+namespace data
+{
+
+DataView *luax_checkdataview(lua_State *L, int idx);
+int luaopen_dataview(lua_State *L);
+
+} // data
+} // love

+ 2 - 2
src/modules/filesystem/wrap_FileData.cpp

@@ -20,7 +20,7 @@
 
 #include "wrap_FileData.h"
 
-#include "common/wrap_Data.h"
+#include "data/wrap_Data.h"
 
 namespace love
 {
@@ -66,7 +66,7 @@ static const luaL_Reg w_FileData_functions[] =
 
 extern "C" int luaopen_filedata(lua_State *L)
 {
-	return luax_register_type(L, &FileData::type, w_Data_functions, w_FileData_functions, nullptr);
+	return luax_register_type(L, &FileData::type, data::w_Data_functions, w_FileData_functions, nullptr);
 }
 
 } // filesystem

+ 2 - 2
src/modules/filesystem/wrap_Filesystem.cpp

@@ -24,7 +24,7 @@
 #include "wrap_File.h"
 #include "wrap_DroppedFile.h"
 #include "wrap_FileData.h"
-#include "common/wrap_Data.h"
+#include "data/wrap_Data.h"
 
 #include "physfs/Filesystem.h"
 
@@ -233,7 +233,7 @@ Data *luax_getdata(lua_State *L, int idx)
 	}
 	else if (luax_istype(L, idx, Data::type))
 	{
-		data = luax_checkdata(L, idx);
+		data = data::luax_checkdata(L, idx);
 		data->retain();
 	}
 

+ 1 - 1
src/modules/font/wrap_Font.cpp

@@ -92,7 +92,7 @@ int w_newTrueTypeRasterizer(lua_State *L)
 
 		if (luax_istype(L, 1, love::Data::type))
 		{
-			d = luax_checkdata(L, 1);
+			d = data::luax_checkdata(L, 1);
 			d->retain();
 		}
 		else

+ 1 - 1
src/modules/font/wrap_GlyphData.cpp

@@ -141,7 +141,7 @@ const luaL_Reg w_GlyphData_functions[] =
 
 extern "C" int luaopen_glyphdata(lua_State *L)
 {
-	return luax_register_type(L, &GlyphData::type, w_Data_functions, w_GlyphData_functions, nullptr);
+	return luax_register_type(L, &GlyphData::type, data::w_Data_functions, w_GlyphData_functions, nullptr);
 }
 
 } // font

+ 1 - 1
src/modules/font/wrap_GlyphData.h

@@ -23,7 +23,7 @@
 
 // LOVE
 #include "common/runtime.h"
-#include "common/wrap_Data.h"
+#include "data/wrap_Data.h"
 
 #include "GlyphData.h"
 

+ 1 - 1
src/modules/font/wrap_Rasterizer.cpp

@@ -20,7 +20,7 @@
 
 #include "wrap_Rasterizer.h"
 
-#include "common/wrap_Data.h"
+#include "data/wrap_Data.h"
 
 namespace love
 {

+ 2 - 2
src/modules/image/wrap_CompressedImageData.cpp

@@ -19,7 +19,7 @@
  **/
 
 #include "wrap_CompressedImageData.h"
-#include "common/wrap_Data.h"
+#include "data/wrap_Data.h"
 
 namespace love
 {
@@ -116,7 +116,7 @@ static const luaL_Reg w_CompressedImageData_functions[] =
 
 extern "C" int luaopen_compressedimagedata(lua_State *L)
 {
-	return luax_register_type(L, &CompressedImageData::type, w_Data_functions, w_CompressedImageData_functions, nullptr);
+	return luax_register_type(L, &CompressedImageData::type, data::w_Data_functions, w_CompressedImageData_functions, nullptr);
 }
 
 } // image

+ 2 - 2
src/modules/image/wrap_Image.cpp

@@ -19,7 +19,7 @@
  **/
 
 #include "wrap_Image.h"
-#include "common/wrap_Data.h"
+#include "data/wrap_Data.h"
 #include "common/Data.h"
 #include "common/StringMap.h"
 
@@ -58,7 +58,7 @@ int w_newImageData(lua_State *L)
 
 		if (luax_istype(L, 4, Data::type))
 		{
-			Data *data = luax_checkdata(L, 4);
+			Data *data = data::luax_checkdata(L, 4);
 			bytes = (const char *) data->getData();
 			numbytes = data->getSize();
 		}

+ 2 - 2
src/modules/image/wrap_ImageData.cpp

@@ -20,7 +20,7 @@
 
 #include "wrap_ImageData.h"
 
-#include "common/wrap_Data.h"
+#include "data/wrap_Data.h"
 #include "filesystem/File.h"
 #include "filesystem/Filesystem.h"
 
@@ -366,7 +366,7 @@ extern "C" int luaopen_imagedata(lua_State *L)
 	pushFormats[PIXELFORMAT_RGBA16F] = luax_pushpixel_rgba16f;
 	pushFormats[PIXELFORMAT_RGBA32F] = luax_pushpixel_rgba32f;
 
-	int ret = luax_register_type(L, &ImageData::type, w_Data_functions, w_ImageData_functions, nullptr);
+	int ret = luax_register_type(L, &ImageData::type, data::w_Data_functions, w_ImageData_functions, nullptr);
 
 	luax_gettypemetatable(L, ImageData::type);
 

+ 12 - 6
src/modules/love/love.cpp

@@ -23,7 +23,6 @@
 #include "common/version.h"
 #include "common/deprecation.h"
 #include "common/runtime.h"
-#include "common/wrap_Data.h"
 
 #include "love.h"
 
@@ -53,8 +52,8 @@
 #ifdef LOVE_ENABLE_ENET
 #	include "libraries/enet/lua-enet.h"
 #endif
-#ifdef LOVE_ENABLE_LUAUTF8
-#	include "libraries/luautf8/lutf8lib.h"
+#ifdef LOVE_ENABLE_LUA53
+#	include "libraries/lua53/lutf8lib.h"
 #endif
 
 // For love::graphics::setGammaCorrect.
@@ -74,6 +73,9 @@ extern "C"
 #if defined(LOVE_ENABLE_AUDIO)
 	extern int luaopen_love_audio(lua_State*);
 #endif
+#if defined(LOVE_ENABLE_DATA)
+	extern int luaopen_love_data(lua_State*);
+#endif
 #if defined(LOVE_ENABLE_EVENT)
 	extern int luaopen_love_event(lua_State*);
 #endif
@@ -133,6 +135,9 @@ static const luaL_Reg modules[] = {
 #if defined(LOVE_ENABLE_AUDIO)
 	{ "love.audio", luaopen_love_audio },
 #endif
+#if defined(LOVE_ENABLE_DATA)
+	{ "love.data", luaopen_love_data },
+#endif
 #if defined(LOVE_ENABLE_EVENT)
 	{ "love.event", luaopen_love_event },
 #endif
@@ -369,8 +374,9 @@ int luaopen_love(lua_State *L)
 	for (int i = 0; modules[i].name != nullptr; i++)
 		love::luax_preload(L, modules[i].func, modules[i].name);
 
-	// Load "common" types.
-	love::w_Data_open(L);
+	// Necessary for Data-creating methods to work properly in Data subclasses.
+	love::luax_require(L, "love.data");
+	lua_pop(L, 1);
 
 #ifdef LOVE_ENABLE_LUASOCKET
 	love::luasocket::__open(L);
@@ -378,7 +384,7 @@ int luaopen_love(lua_State *L)
 #ifdef LOVE_ENABLE_ENET
 	love::luax_preload(L, luaopen_enet, "enet");
 #endif
-#ifdef LOVE_ENABLE_LUAUTF8
+#ifdef LOVE_ENABLE_LUA53
 	love::luax_preload(L, luaopen_luautf8, "utf8");
 #endif
 

+ 0 - 186
src/modules/math/MathModule.cpp

@@ -21,7 +21,6 @@
 // LOVE
 #include "MathModule.h"
 #include "common/Vector.h"
-#include "common/b64.h"
 #include "common/int.h"
 #include "common/StringMap.h"
 #include "BezierCurve.h"
@@ -41,84 +40,6 @@ using love::Vector2;
 namespace
 {
 
-static const char hexchars[] = "0123456789abcdef";
-
-char *bytesToHex(const love::uint8 *src, size_t srclen, size_t &dstlen)
-{
-	dstlen = srclen * 2;
-
-	if (dstlen == 0)
-		return nullptr;
-
-	char *dst = nullptr;
-	try
-	{
-		dst = new char[dstlen + 1];
-	}
-	catch (std::exception &)
-	{
-		throw love::Exception("Out of memory.");
-	}
-
-	for (size_t i = 0; i < srclen; i++)
-	{
-		love::uint8 b = src[i];
-		dst[i * 2 + 0] = hexchars[b >> 4];
-		dst[i * 2 + 1] = hexchars[b & 0xF];
-	}
-
-	dst[dstlen] = '\0';
-	return dst;
-}
-
-love::uint8 nibble(char c)
-{
-	if (c >= '0' && c <= '9')
-		return (love::uint8) (c - '0');
-
-	if (c >= 'A' && c <= 'F')
-		return (love::uint8) (c - 'A' + 0x0a);
-
-	if (c >= 'a' && c <= 'f')
-		return (love::uint8) (c - 'a' + 0x0a);
-
-	return 0;
-}
-
-love::uint8 *hexToBytes(const char *src, size_t srclen, size_t &dstlen)
-{
-	if (srclen >= 2 && src[0] == '0' && (src[1] == 'x' || src[1] == 'X'))
-	{
-		src += 2;
-		srclen -= 2;
-	}
-
-	dstlen = (srclen + 1) / 2;
-
-	if (dstlen == 0)
-		return nullptr;
-
-	love::uint8 *dst = nullptr;
-	try
-	{
-		dst = new love::uint8[dstlen];
-	}
-	catch (std::exception &)
-	{
-		throw love::Exception("Out of memory.");
-	}
-
-	for (size_t i = 0; i < dstlen; i++)
-	{
-		dst[i] = nibble(src[i * 2]) << 4;
-
-		if (i * 2 + 1 < srclen)
-			dst[i] |= nibble(src[i * 2 + 1]);
-	}
-
-	return dst;
-}
-
 // check if an angle is oriented counter clockwise
 inline bool is_oriented_ccw(const Vector2 &a, const Vector2 &b, const Vector2 &c)
 {
@@ -280,81 +201,6 @@ float linearToGamma(float c)
 		return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
 }
 
-CompressedData *compress(Compressor::Format format, love::Data *rawdata, int level)
-{
-	return compress(format, (const char *) rawdata->getData(), rawdata->getSize(), level);
-}
-
-CompressedData *compress(Compressor::Format format, const char *rawbytes, size_t rawsize, int level)
-{
-	Compressor *compressor = Compressor::getCompressor(format);
-
-	if (compressor == nullptr)
-		throw love::Exception("Invalid compression format.");
-
-	size_t compressedsize = 0;
-	char *cbytes = compressor->compress(format, rawbytes, rawsize, level, compressedsize);
-
-	CompressedData *data = nullptr;
-
-	try
-	{
-		data = new CompressedData(format, cbytes, compressedsize, rawsize, true);
-	}
-	catch (love::Exception &)
-	{
-		delete[] cbytes;
-		throw;
-	}
-
-	return data;
-}
-
-char *decompress(CompressedData *data, size_t &decompressedsize)
-{
-	size_t rawsize = data->getDecompressedSize();
-
-	char *rawbytes = decompress(data->getFormat(), (const char *) data->getData(),
-	                            data->getSize(), rawsize);
-
-	decompressedsize = rawsize;
-	return rawbytes;
-}
-
-char *decompress(Compressor::Format format, const char *cbytes, size_t compressedsize, size_t &rawsize)
-{
-	Compressor *compressor = Compressor::getCompressor(format);
-
-	if (compressor == nullptr)
-		throw love::Exception("Invalid compression format.");
-
-	return compressor->decompress(format, cbytes, compressedsize, rawsize);
-}
-
-char *encode(EncodeFormat format, const char *src, size_t srclen, size_t &dstlen, size_t linelen)
-{
-	switch (format)
-	{
-	case ENCODE_BASE64:
-	default:
-		return b64_encode(src, srclen, linelen, dstlen);
-	case ENCODE_HEX:
-		return bytesToHex((const uint8 *) src, srclen, dstlen);
-	}
-}
-
-char *decode(EncodeFormat format, const char *src, size_t srclen, size_t &dstlen)
-{
-	switch (format)
-	{
-	case ENCODE_BASE64:
-	default:
-		return b64_decode(src, srclen, dstlen);
-	case ENCODE_HEX:
-		return (char *) hexToBytes(src, srclen, dstlen);
-	}
-}
-
 Math Math::instance;
 
 Math::Math()
@@ -392,37 +238,5 @@ Transform *Math::newTransform(float x, float y, float a, float sx, float sy, flo
 	return new Transform(x, y, a, sx, sy, ox, oy, kx, ky);
 }
 
-std::string hash(HashFunction::Function function, Data *input)
-{
-	return hash(function, (const char*) input->getData(), input->getSize());
-}
-
-std::string hash(HashFunction::Function function, const char *input, uint64_t size)
-{
-	HashFunction *hashfunction = HashFunction::getHashFunction(function);
-	if (hashfunction == nullptr)
-		throw love::Exception("Invalid hash function.");
-
-	return hashfunction->hash(function, input, size);
-}
-
-static StringMap<EncodeFormat, ENCODE_MAX_ENUM>::Entry encoderEntries[] =
-{
-	{ "base64", ENCODE_BASE64 },
-	{ "hex",    ENCODE_HEX },
-};
-
-static StringMap<EncodeFormat, ENCODE_MAX_ENUM> encoders(encoderEntries, sizeof(encoderEntries));
-
-bool getConstant(const char *in, EncodeFormat &out)
-{
-	return encoders.find(in, out);
-}
-
-bool getConstant(EncodeFormat in, const char *&out)
-{
-	return encoders.find(in, out);
-}
-
 } // math
 } // love

+ 0 - 63
src/modules/math/MathModule.h

@@ -22,9 +22,6 @@
 #define LOVE_MATH_MODMATH_H
 
 #include "RandomGenerator.h"
-#include "CompressedData.h"
-#include "Compressor.h"
-#include "HashFunction.h"
 
 // LOVE
 #include "common/Module.h"
@@ -55,13 +52,6 @@ struct Triangle
 	Vector2 a, b, c;
 };
 
-enum EncodeFormat
-{
-	ENCODE_BASE64,
-	ENCODE_HEX,
-	ENCODE_MAX_ENUM
-};
-
 /**
  * Triangulate a simple polygon.
  *
@@ -98,59 +88,6 @@ static float noise2(float x, float y);
 static float noise3(float x, float y, float z);
 static float noise4(float x, float y, float z, float w);
 
-/**
- * Compresses a block of memory using the given compression format.
- *
- * @param format The compression format to use.
- * @param rawdata The data to compress.
- * @param level The amount of compression to apply (between 0 and 9.)
- *              A value of -1 indicates the default amount of compression.
- *              Specific formats may not use every level.
- * @return The newly compressed data.
- **/
-CompressedData *compress(Compressor::Format format, Data *rawdata, int level = -1);
-CompressedData *compress(Compressor::Format format, const char *rawbytes, size_t rawsize, int level = -1);
-
-/**
- * Decompresses existing compressed data into raw bytes.
- *
- * @param[in] data The compressed data to decompress.
- * @param[out] decompressedsize The size in bytes of the decompressed data.
- * @return The newly decompressed data (allocated with new[]).
- **/
-char *decompress(CompressedData *data, size_t &decompressedsize);
-
-/**
- * Decompresses existing compressed data into raw bytes.
- *
- * @param[in] format The compression format the data is in.
- * @param[in] cbytes The compressed data to decompress.
- * @param[in] compressedsize The size in bytes of the compressed data.
- * @param[in,out] rawsize On input, the size in bytes of the original
- *               uncompressed data, or 0 if unknown. On return, the size in
- *               bytes of the newly decompressed data.
- * @return The newly decompressed data (allocated with new[]).
- **/
-char *decompress(Compressor::Format format, const char *cbytes, size_t compressedsize, size_t &rawsize);
-
-char *encode(EncodeFormat format, const char *src, size_t srclen, size_t &dstlen, size_t linelen = 0);
-char *decode(EncodeFormat format, const char *src, size_t srclen, size_t &dstlen);
-
-/**
- * Hash the input, producing an set of bytes as output.
- *
- * @param[in] function The selected hash function.
- * @param[in] input The input data to hash.
- * @return An std::string of bytes, representing the result of the hash
- *         function.
- **/
-std::string hash(HashFunction::Function function, Data *input);
-std::string hash(HashFunction::Function function, const char *input, uint64_t size);
-
-
-bool getConstant(const char *in, EncodeFormat &out);
-bool getConstant(EncodeFormat in, const char *&out);
-
 
 class Math : public Module
 {

+ 14 - 96
src/modules/math/wrap_Math.cpp

@@ -21,12 +21,14 @@
 #include "wrap_Math.h"
 #include "wrap_RandomGenerator.h"
 #include "wrap_BezierCurve.h"
-#include "wrap_CompressedData.h"
 #include "wrap_Transform.h"
 #include "MathModule.h"
 #include "BezierCurve.h"
 #include "Transform.h"
-#include "common/b64.h"
+
+#include "data/wrap_DataModule.h"
+#include "data/wrap_CompressedData.h"
+#include "data/DataModule.h"
 
 #include <cmath>
 #include <iostream>
@@ -348,6 +350,9 @@ int w_noise(lua_State *L)
 
 int w_compress(lua_State *L)
 {
+	using namespace love::data;
+	luax_markdeprecated(L, "love.math.compress", API_FUNCTION, DEPRECATED_REPLACED, "love.data.compress");
+
 	const char *fstr = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2);
 	Compressor::Format format = Compressor::FORMAT_LZ4;
 
@@ -370,11 +375,15 @@ int w_compress(lua_State *L)
 	}
 
 	luax_pushtype(L, cdata);
+	cdata->release();
 	return 1;
 }
 
 int w_decompress(lua_State *L)
 {
+	using namespace love::data;
+	luax_markdeprecated(L, "love.math.decompress", API_FUNCTION, DEPRECATED_REPLACED, "love.data.decompress");
+
 	char *rawbytes = nullptr;
 	size_t rawsize = 0;
 
@@ -413,96 +422,6 @@ int w_decompress(lua_State *L)
 	return 1;
 }
 
-int w_encode(lua_State *L)
-{
-	const char *formatstr = luaL_checkstring(L, 1);
-	EncodeFormat format;
-	if (!getConstant(formatstr, format))
-		return luaL_error(L, "Invalid encode format: %s", formatstr);
-
-	size_t srclen = 0;
-	const char *src = nullptr;
-
-	if (luax_istype(L, 2, Data::type))
-	{
-		Data *data = luax_totype<Data>(L, 2);
-		src = (const char *) data->getData();
-		srclen = data->getSize();
-	}
-	else
-		src = luaL_checklstring(L, 2, &srclen);
-
-	size_t linelen = (size_t) luaL_optinteger(L, 3, 0);
-
-	size_t dstlen = 0;
-	char *dst = nullptr;
-	luax_catchexcept(L, [&](){ dst = encode(format, src, srclen, dstlen, linelen); });
-
-	if (dst != nullptr)
-		lua_pushlstring(L, dst, dstlen);
-	else
-		lua_pushstring(L, "");
-
-	delete[] dst;
-	return 1;
-}
-
-int w_decode(lua_State *L)
-{
-	const char *formatstr = luaL_checkstring(L, 1);
-	EncodeFormat format;
-	if (!getConstant(formatstr, format))
-		return luaL_error(L, "Invalid decode format: %s", formatstr);
-
-	size_t srclen = 0;
-	const char *src = nullptr;
-
-	if (luax_istype(L, 2, Data::type))
-	{
-		Data *data = luax_totype<Data>(L, 2);
-		src = (const char *) data->getData();
-		srclen = data->getSize();
-	}
-	else
-		src = luaL_checklstring(L, 2, &srclen);
-
-	size_t dstlen = 0;
-	char *dst = nullptr;
-	luax_catchexcept(L, [&](){ dst = decode(format, src, srclen, dstlen); });
-
-	if (dst != nullptr)
-		lua_pushlstring(L, dst, dstlen);
-	else
-		lua_pushstring(L, "");
-
-	delete[] dst;
-	return 1;
-}
-
-int w_hash(lua_State *L)
-{
-	const char *fstr = luaL_checkstring(L, 1);
-	HashFunction::Function function;
-	if (!HashFunction::getConstant(fstr, function))
-		return luaL_error(L, "Invalid hash function: %s", fstr);
-
-	std::string hash;
-	if (lua_isstring(L, 2))
-	{
-		size_t rawsize = 0;
-		const char *rawbytes = luaL_checklstring(L, 2, &rawsize);
-		luax_catchexcept(L, [&](){ hash = love::math::hash(function, rawbytes, rawsize); });
-	}
-	else
-	{
-		Data *rawdata = luax_checktype<Data>(L, 2);
-		luax_catchexcept(L, [&](){ hash = love::math::hash(function, rawdata); });
-	}
-
-	luax_pushstring(L, hash);
-	return 1;
-}
-
 // C functions in a struct, necessary for the FFI versions of math functions.
 struct FFI_Math
 {
@@ -540,11 +459,11 @@ static const luaL_Reg functions[] =
 	{ "gammaToLinear", w_gammaToLinear },
 	{ "linearToGamma", w_linearToGamma },
 	{ "noise", w_noise },
+
+	// Deprecated.
 	{ "compress", w_compress },
 	{ "decompress", w_decompress },
-	{ "encode", w_encode },
-	{ "decode", w_decode },
-	{ "hash", w_hash },
+
 	{ 0, 0 }
 };
 
@@ -552,7 +471,6 @@ static const lua_CFunction types[] =
 {
 	luaopen_randomgenerator,
 	luaopen_beziercurve,
-	luaopen_compresseddata,
 	luaopen_transform,
 	0
 };

+ 2 - 2
src/modules/sound/wrap_SoundData.cpp

@@ -20,7 +20,7 @@
 
 #include "wrap_SoundData.h"
 
-#include "common/wrap_Data.h"
+#include "data/wrap_Data.h"
 
 // Shove the wrap_SoundData.lua code directly into a raw string literal.
 static const char sounddata_lua[] =
@@ -130,7 +130,7 @@ static const luaL_Reg w_SoundData_functions[] =
 
 extern "C" int luaopen_sounddata(lua_State *L)
 {
-	int ret = luax_register_type(L, &SoundData::type, w_Data_functions, w_SoundData_functions, nullptr);
+	int ret = luax_register_type(L, &SoundData::type, data::w_Data_functions, w_SoundData_functions, nullptr);
 
 	luax_gettypemetatable(L, SoundData::type);
 

+ 2 - 0
src/scripts/boot.lua

@@ -387,6 +387,7 @@ function love.init()
 			highdpi = false,
 		},
 		modules = {
+			data = true,
 			event = true,
 			keyboard = true,
 			mouse = true,
@@ -453,6 +454,7 @@ function love.init()
 
 	-- Gets desired modules.
 	for k,v in ipairs{
+		"data",
 		"thread",
 		"timer",
 		"event",

+ 2 - 0
src/scripts/boot.lua.h

@@ -716,6 +716,7 @@ const unsigned char boot_lua[] =
 	0x2c, 0x0a,
 	0x09, 0x09, 0x7d, 0x2c, 0x0a,
 	0x09, 0x09, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
+	0x09, 0x09, 0x09, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a,
 	0x09, 0x09, 0x09, 0x6b, 0x65, 0x79, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 
 	0x2c, 0x0a,
@@ -841,6 +842,7 @@ const unsigned char boot_lua[] =
 	0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x0a,
 	0x09, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 
 	0x7b, 0x0a,
+	0x09, 0x09, 0x22, 0x64, 0x61, 0x74, 0x61, 0x22, 0x2c, 0x0a,
 	0x09, 0x09, 0x22, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x22, 0x2c, 0x0a,
 	0x09, 0x09, 0x22, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x22, 0x2c, 0x0a,
 	0x09, 0x09, 0x22, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x2c, 0x0a,

+ 1 - 1
src/scripts/nogame.lua

@@ -923,7 +923,7 @@ function love.nogame()
 		love.graphics.setBackgroundColor(136/255, 193/255, 206/255)
 
 		local function load_image(file, name, flags)
-			local decoded = love.math.decode("base64", file)
+			local decoded = love.data.decode("base64", file)
 			return love.graphics.newImage(love.filesystem.newFileData(decoded, name:gsub("_", ".")), flags)
 		end
 

+ 1 - 1
src/scripts/nogame.lua.h

@@ -3540,7 +3540,7 @@ const unsigned char nogame_lua[] =
 	0x6f, 0x61, 0x64, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x2c, 0x20, 0x6e, 0x61, 
 	0x6d, 0x65, 0x2c, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x20, 0x3d, 
-	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x28, 
+	0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x28, 
 	0x22, 0x62, 0x61, 0x73, 0x65, 0x36, 0x34, 0x22, 0x2c, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x29, 0x0a,
 	0x09, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x2e, 0x67, 0x72, 0x61, 
 	0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6e, 0x65, 0x77, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x28, 0x6c, 0x6f, 0x76,