1. --!parent
  2. --!encoding=utf-8
  3.  
  4. --****************************************************************************
  5. -- Software: BYTEARRAY_ENCODER
  6. -- Version:  0.6
  7. -- Date:     2009-04-18
  8. -- Author:   Valentin Schmidt
  9. --
  10. -- Supported data types:
  11. -- #list
  12. -- #propList
  13. -- #bytearray
  14. -- #string
  15. -- #symbol
  16. -- #integer
  17. -- #float (either using lingo ( = slow) or crypto xtra ( = fast))
  18. -- #image
  19. -- #void
  20. -- #date
  21. -- #point, #rect, #vector, #transform (all coords stored as floats)
  22. -- #color
  23. -- #sprite, #member, #castlib
  24. -- #media (requires crypto xtra!)
  25. -- core objects (#_player, #_movie, ...)
  26. -- all other types that can be stored/restored by using string(...)/value(...)
  27. --
  28. -- Usage:
  29. --  v = [1,2,"hellö<>#+~",["foo":"bar", #foo2:#bar2], member("test").image]
  30. --  enc = script("BYTEARRAY_ENCODER")
  31. --  m = new(#bytearray)
  32. --  m.bytearray = enc.mEncodeData(v)
  33. --  put enc.mDecodeData(m.bytearray)
  34. --
  35. --****************************************************************************
  36.  
  37. ----------------------------------------
  38. -- v: arbitrary (supported) value
  39. -- returns: bytearray
  40. ----------------------------------------
  41. on mEncodeData (me, v)
  42.   baData = bytearray()
  43.   me._encode(v, baData)
  44.   return baData
  45. end
  46.  
  47. ----------------------------------------
  48. -- baData: encoded value as bytearray
  49. -- returns: value
  50. ----------------------------------------
  51. on mDecodeData (me, baData)
  52.   baData.position = 1
  53.   return me._decode(baData)
  54. end
  55.  
  56. ----------------------------------------
  57. -- similar to mEncodeData, but expects linear list and creates valid RIFF file
  58. --
  59. -- tList: list of arbitrary values
  60. -- returns: bytearray
  61. ----------------------------------------
  62. on mEncodeDataRIFF (me, tList)
  63.   baData = bytearray()
  64.   baData.writeRawString("RIFF", 4)
  65.   baData.writeInt32(0) -- update later
  66.   baData.writeRawString("BYARdata", 8)
  67.   baData.writeInt32(0) -- update later
  68.   cnt = count(tList)
  69.   repeat with i = 1 to cnt
  70.     me._encode(tList[i], baData)
  71.   end repeat
  72.   len = baData.position-17-4
  73.   baData.position = 17
  74.   baData.writeInt32(len)
  75.   baData.position = 5
  76.   baData.writeInt32(baData.length-8)
  77.   baData.position = 1
  78.   return baData
  79. end
  80.  
  81. ----------------------------------------
  82. -- similar to mDecodeData, but based on valid RIFF file created with mEncodeDataRIFF
  83. --
  84. -- baData: encoded list as bytearray (RIFF version)
  85. -- returns: list
  86. ----------------------------------------
  87. on mDecodeDataRIFF (me, baData)
  88.   v = []
  89.   baData.position = 17
  90.   len = baData.readInt32()
  91.   pos = baData.position
  92.   repeat while true
  93.     v.add(me._decode(baData))
  94.     if baData.position> = pos+len then exit repeat
  95.   end repeat
  96.   return v
  97. end
  98.  
  99. ----------------------------------------
  100. --
  101. ----------------------------------------
  102. on _encode (me, v, baData)
  103.   t = ilk(v)
  104.   baData.writeRawString(string(t).char[1..4], 4)
  105.  
  106.   case (t) of
  107.     #list:
  108.       cnt = count(v)
  109.       baData.writeInt32(cnt)
  110.       repeat with i = 1 to cnt
  111.         me._encode(v[i], baData)
  112.       end repeat
  113.      
  114.     #proplist:
  115.       cnt = count(v)
  116.       baData.writeInt32(cnt)
  117.       repeat with i = 1 to cnt
  118.         me._encode(v.getPropAt(i), baData)
  119.         me._encode(v[i], baData)
  120.       end repeat
  121.      
  122.     #bytearray:
  123.       baData.writeInt32(v.length)
  124.       baData.writeByteArray(v)
  125.      
  126.     #string:
  127.       baData.writeString(v)
  128.      
  129.     #symbol:
  130.       baData.writeString(string(v))
  131.      
  132.     #integer:
  133.       baData.writeInt32(v)
  134.      
  135.     #float:
  136.       me.writeDouble(baData, v)
  137.      
  138.     #image:
  139.       baData.writeInt16(v.width)
  140.       baData.writeInt16(v.height)
  141.       baData.writeInt8(v.depth)
  142.       case (v.depth) of
  143.         32:
  144.           --          if v.useAlpha then
  145.           baData.writeByteArray(v.getPixels(#BGRA8888))
  146.           --          else
  147.           --            pData.writeByteArray(v.getPixels(#BGR888))
  148.           --          end if
  149.         24:
  150.           baData.writeByteArray(v.getPixels(#BGR888))
  151.         16:
  152.           cntx = v.width-1
  153.           cnty = v.height-1
  154.           repeat with y = 0 to cnty
  155.             repeat with x = 0 to cntx
  156.               baData.writeInt16(v.getPixel(x,y,#integer))
  157.             end repeat
  158.           end repeat
  159.         8:
  160.           cntx = v.width-1
  161.           cnty = v.height-1
  162.           repeat with y = 0 to cnty
  163.             repeat with x = 0 to cntx
  164.               baData.writeInt8(v.getPixel(x,y,#integer))
  165.             end repeat
  166.           end repeat
  167.         4:-- TODO
  168.         2:
  169.         1:
  170.       end case
  171.      
  172.     #void: --> will be VOID
  173.       nothing
  174.      
  175.     #point:
  176.       me.writeDouble(baData, v.locH)
  177.       me.writeDouble(baData, v.locV)
  178.      
  179.     #vector:
  180.       me.writeDouble(baData, v.x)
  181.       me.writeDouble(baData, v.y)
  182.       me.writeDouble(baData, v.z)
  183.      
  184.     #rect:
  185.       me.writeDouble(baData, v.left)
  186.       me.writeDouble(baData, v.top)
  187.       me.writeDouble(baData, v.right)
  188.       me.writeDouble(baData, v.bottom)
  189.      
  190.     #transform:
  191.       me.writeDouble(baData, v.scale.x)
  192.       me.writeDouble(baData, v.scale.y)
  193.       me.writeDouble(baData, v.scale.z)
  194.       me.writeDouble(baData, v.position.x)
  195.       me.writeDouble(baData, v.position.y)
  196.       me.writeDouble(baData, v.position.z)
  197.       me.writeDouble(baData, v.rotation.x)
  198.       me.writeDouble(baData, v.rotation.y)
  199.       me.writeDouble(baData, v.rotation.z)
  200.       me.writeDouble(baData, v.axisangle[1].x)
  201.       me.writeDouble(baData, v.axisangle[1].y)
  202.       me.writeDouble(baData, v.axisangle[1].z)
  203.       me.writeDouble(baData, v.axisangle[2])
  204.      
  205.     #date: -- save as 8 bytes
  206.       baData.writeInt16(v.year)
  207.       baData.writeInt8(v.month)
  208.       baData.writeInt8(v.day)
  209.       baData.writeInt32(v.seconds)
  210.      
  211.     #color:
  212.       baData.writeInt8(v.red)
  213.       baData.writeInt8(v.green)
  214.       baData.writeInt8(v.blue)
  215.      
  216.     #sprite:
  217.       baData.writeInt16(v.spriteNum)
  218.      
  219.     #member:
  220.       baData.writeInt16(v.memberNum)
  221.       baData.writeInt16(v.castLibNum)
  222.      
  223.     #castLib:
  224.       baData.writeInt16(v.number)
  225.      
  226.     #media: -- requires CRYPTO XTRA
  227.       ba = cx_media_to_bytearray(v)
  228.       baData.writeByteArray(ba)
  229.      
  230.     otherwise: -- everything that can be evaluated directly using value()...?
  231.       s = string(v)
  232.       if s.word[1] = "<Object" then -- core objects, e.g. _movie, _player, ...
  233.         baData.writeString(s.word[2])
  234.       else if s.word[1] = "<Xtra" AND s.word[2]<>"child" then -- xtra refs (no instances)
  235.         s = s.word[1..2]
  236.         delete char 1 of s
  237.         baData.writeString(s)
  238.       else
  239.         baData.writeString(s)
  240.       end if
  241.   end case
  242. end
  243.  
  244. ----------------------------------------
  245. --
  246. ----------------------------------------
  247. on _decode (me, baData)
  248.   t = baData.readRawString(4)
  249.  
  250.   case (t) of
  251.     "list":
  252.       v = []
  253.       cnt = baData.readInt32()
  254.       repeat with i = 1 to cnt
  255.         v.add(me._decode(baData))
  256.       end repeat
  257.      
  258.     "prop":
  259.       v = [:]
  260.       cnt = baData.readInt32()
  261.       repeat with i = 1 to cnt
  262.         p = me._decode(baData)
  263.         vl = me._decode(baData)
  264.         v.addProp(p, vl)
  265.       end repeat
  266.      
  267.     "byte":
  268.       len = baData.readInt32()
  269.       v = baData.readByteArray(len)
  270.      
  271.     "stri":
  272.       v = baData.readString()
  273.      
  274.     "symb":
  275.       v = symbol(baData.readString())
  276.      
  277.     "inte":
  278.       v = baData.readInt32()
  279.      
  280.     "floa":
  281.       v = me.readDouble(baData)
  282.      
  283.     "imag":
  284.       w = baData.readInt16()
  285.       h = baData.readInt16()
  286.       d = baData.readInt8()
  287.       v = image(w,h,d)
  288.       case (d) of
  289.         32:
  290.           ba = baData.readByteArray(w*h*4)
  291.           v.setPixels(ba, #BGRA8888)
  292.         24:
  293.           ba = baData.readByteArray(w*h*3)
  294.           v.setPixels(ba, #BGR888)
  295.         16:
  296.           ba = baData.readByteArray(w*h*2)
  297.           cntx = w-1
  298.           cnty = h-1
  299.           repeat with y = 0 to cnty
  300.             repeat with x = 0 to cntx
  301.               v.setPixel(x,y, baData.readInt16(), #integer)
  302.             end repeat
  303.           end repeat
  304.         8:
  305.           ba = baData.readByteArray(w*h)
  306.           cntx = w-1
  307.           cnty = h-1
  308.           repeat with y = 0 to cnty
  309.             repeat with x = 0 to cntx
  310.               v.setPixel(x,y, baData.readInt8(), #integer)
  311.             end repeat
  312.           end repeat
  313.         4: -- TODO
  314.         2:
  315.         1:
  316.       end case
  317.      
  318.     "medi": -- requires CRYPTO XTRA
  319.       len = baData.readInt32()
  320.       ba = baData.readByteArray(len)
  321.       v = cx_bytearray_to_media(ba) -- TODO
  322.      
  323.     "void":
  324.       nothing -- or: v = VOID
  325.      
  326.     "poin":
  327.       v = point(me.readDouble(baData),me.readDouble(baData))
  328.      
  329.     "vect":
  330.       v = vector(me.readDouble(baData),me.readDouble(baData),me.readDouble(baData))
  331.      
  332.     "rect":
  333.       v = rect(me.readDouble(baData),me.readDouble(baData),me.readDouble(baData),me.readDouble(baData))
  334.      
  335.     "tran":
  336.       v = transform()
  337.       v.scale = vector(me.readDouble(baData),me.readDouble(baData),me.readDouble(baData))
  338.       v.position = vector(me.readDouble(baData),me.readDouble(baData),me.readDouble(baData))
  339.       v.rotation = vector(me.readDouble(baData),me.readDouble(baData),me.readDouble(baData))
  340.       v.axisangle[1] = vector(me.readDouble(baData),me.readDouble(baData),me.readDouble(baData))
  341.       v.axisangle[2] = me.readDouble(baData)
  342.      
  343.     "date":
  344.       y = baData.readInt16()
  345.       m = baData.readInt8()
  346.       d = baData.readInt8()
  347.       s = baData.readInt32()
  348.       v = date(y,m,d)
  349.       v.seconds = s
  350.      
  351.     "colo":
  352.       v = RGB(baData.readInt8(),baData.readInt8(),baData.readInt8())
  353.      
  354.     "spri":
  355.       v = sprite(baData.readInt16())
  356.      
  357.     "memb":
  358.       v = member(baData.readInt16(),baData.readInt16())
  359.      
  360.     "cast":
  361.       v = castLib(baData.readInt16())
  362.      
  363.     otherwise: -- everything that can be evaluated directly using value()...?
  364.       v = value(baData.readString())
  365.      
  366.   end case
  367.  
  368.   return v
  369. end
  370.  
  371. ----------------------------------------
  372. -- select a method
  373. ----------------------------------------
  374. on writeDouble (me, baData, v)
  375.   -- A) SAVE FLOAT AS DOUBLE PRECISION IEEE-754 ( = 8 bytes, uses lingo, SLOW!)
  376.   writeDouble_lingo(baData, v)
  377.  
  378.   -- B) SAVE FLOAT AS DOUBLE PRECISION IEEE-754 ( = 8 bytes, requires CRYPTO XTRA v0.9+)
  379.   -- cx_writeDouble(baData, v)
  380.  
  381.   -- C) SAVE FLOAT AS STRING REPRESENTATION (with max. floatprecision = 15)
  382.   -- op = the floatprecision
  383.   -- the floatprecision = 15
  384.   -- baData.writeString(string(v))
  385.   -- the floatprecision = op
  386.  
  387.   -- D) SAVE AS INT (IN CASE IT'S ACTUALLY AN INT)
  388.   -- baData.writeInt32(v)
  389. end
  390.  
  391. ----------------------------------------
  392. -- select a method
  393. ----------------------------------------
  394. on readDouble (me, baData)
  395.   -- A) FLOAT AS DOUBLE PRECISION IEEE-754 ( = 8 bytes, uses lingo, SLOW!)
  396.   return readDouble_lingo(baData)
  397.  
  398.   -- B) FLOAT AS DOUBLE PRECISION IEEE-754 ( = 8 bytes, requires CRYPTO XTRA v0.9+)
  399.   -- return cx_readDouble(baData)
  400.  
  401.   -- C) FLOAT AS STRING REPRESENTATION (with max. floatprecision = 15)
  402.   -- return float(baData.readString())
  403.  
  404.   -- D) AS INT (IN CASE IT'S ACTUALLY AN INT)
  405.   -- return baData.readInt32()
  406. end
  407.  
  408. ----------------------------------------
  409. -- WRITES FLOAT AS DOUBLE-PRECISION IEEE-754 TO BYTEARARY
  410. ----------------------------------------
  411. on writeDouble_lingo(ba, v)
  412.   bits = []
  413.   bits[64] = 0
  414.   bits[1] = (v<0) -- sign bit
  415.   BinVal = []
  416.   BinVal[2102] = 0
  417.   -- seperate integer and decimal parts
  418.   val = abs(v)
  419.   intpart = bitOr(val, 0) -- floor
  420.   decpart = val - intpart
  421.   -- convert integer part
  422.   index1 = 1024
  423.   repeat while (((intpart<>0) > 0) AND (index1 > =  0))
  424.     BinVal[index1 +1] = intpart mod 2
  425.     intpart = intpart / 2
  426.     index1 = index1-1
  427.   end repeat
  428.   -- convert decimal part
  429.   index1 = 1025
  430.   repeat while ((decpart > 0) AND (index1 < 2102))
  431.     decpart = decpart*2
  432.     if (decpart > =  1) then
  433.       BinVal[index1 +1] = 1
  434.       decpart = decpart-1
  435.     else
  436.       BinVal[index1 +1] = 0
  437.     end if
  438.     index1 = index1+1
  439.   end repeat
  440.   -- find most significant bit of significand
  441.   index1 = BinVal.getPos(1)-1
  442.   if index1<0 then index1 = 2102
  443.   binexpnt = 1024 - index1
  444.   if ((binexpnt > =  -1022) AND (binexpnt < =  1023)) then
  445.     index1 = index1+1
  446.   else if (binexpnt < -1022) then
  447.     binexpnt = -1023
  448.     index1 = 1024 - binexpnt
  449.   end if
  450.   -- copy the result
  451.   index2 = 12
  452.   repeat while ((index2 < 64) AND (index1 < 2102))
  453.     bits[index2 +1] = BinVal[index1 +1]
  454.     index2 = index2+1
  455.     index1 = index1+1
  456.   end repeat
  457.   -- convert exponent value to binary representation
  458.   index1 = 11
  459.   binexpnt = binexpnt+1023
  460.   repeat while (binexpnt>0)
  461.     bits[index1 +1] = binexpnt mod 2
  462.     binexpnt = binexpnt / 2
  463.     index1 = index1-1
  464.   end repeat
  465.   -- save 64 bits as 8 bytes in bytearray
  466.   repeat with i = 7 down to 0
  467.     s = 0
  468.     d = 1
  469.     repeat with j = 1 to 8
  470.       n = i*8+9-j
  471.       s = s + bits[n]*d
  472.       d = d*2
  473.     end repeat
  474.     ba.writeInt8(s)
  475.   end repeat
  476. end
  477.  
  478. ----------------------------------------
  479. -- READS FLOAT AS DOUBLE-PRECISION IEEE-754 FROM BYTEARARY
  480. ----------------------------------------
  481. on readDouble_lingo(ba)
  482.   -- read 8 bytes from bytearray as 64 bits
  483.   bits = []
  484.   f = [128,64,32,16,8,4,2,1]
  485.   repeat with i = 7 down to 0
  486.     n = ba.readInt8()
  487.     i8 = i*8
  488.     repeat with j = 1 to 8
  489.       k = f[j]
  490.       bits[i8 + j] = integer( bitAnd(k, n)/k)
  491.     end repeat
  492.   end repeat
  493.   -- convert bits to float
  494.   expo = 0
  495.   d = 1
  496.   repeat with i = 1 to 11
  497.     expo = expo + d *  bits[13 - i]
  498.     d = d*2
  499.   end repeat
  500.   expo = expo - 1023
  501.   frac = 0.0
  502.   d = 1.0
  503.   repeat with i = 1 to 52
  504.     frac = frac + d *  bits[65 - i]
  505.     d = d*2
  506.   end repeat
  507.   frac = frac / 4503599627370496.0
  508.   v = power(2, expo) * (1+frac)
  509.   if bits[1] then v = -v
  510.   return v
  511. end
  512.  
[raw code]