RE: even better coerce to record with usrf
RE: even better coerce to record with usrf
- Subject: RE: even better coerce to record with usrf
- From: Nigel Garvey <email@hidden>
- Date: Fri, 14 Dec 2001 01:10:05 +0000
Olof Hellman wrote on Wed, 12 Dec 2001 17:42:11 -0800:
>
JJ chipped in:
>
> set entry_1 to record {+class usrf;:{"status", "unproc"}}
>
> set entry_2 to record {+class usrf;:{"lyrics", false}}
>
>
>
> set Entire_Record to entry_1 & entry_2
>
>
>
> -- That's >> {status:"unproc",lyrics:false}
Or, of course (if it hasn't already been mentioned):
set Entire_Record to record {+class usrf;:{"status", "unproc",
"lyrics", false}}
>
which is brilliant!!! This speeds up the cycle by about half by getting
>
rid of one 'run script' :
>
>
to usrf(theList)
>
return record {+class usrf;:theList }
>
end usrf
>
>
to extract_record_field(theRecord, theField)
>
run script " on run{r}
>
return |"& fieldName & "| of r
>
end " with parameters {theRecord}
>
end extract_record_field
>
>
set usrfRecord to usrf( {serial number", 75757575 })
>
extract_record_field( usrfRecord, "serial number" )
>
--> 75757575
>
>
>
Can anyone figure out how to get rid of the other run script?
Well, if you don't mind exploiting the bug that was being discussed the
other day (and which Arthur used to good effect in a couple of scripts),
you can use the following. It looks long, it is crude, but it's quite
fast.
to usrf(theList)
return record {+class usrf;:theList}
end usrf
to extract_record_field(theRecord, theField)
-- Exploit a bug to coerce the record to string
set recInStr to {theRecord} as string
-- Get a similar string for a one-item record
-- consisting of the requested label and a dummy value
set recOutStr to {usrf({theField, ""})} as string
-- Use the label string as a text item delimiter
-- Ensure it's unique by including it's 4-byte length value too
set labelDelim to numAs4bytes(theField's length) & theField
set AppleScript's text item delimiters to {labelDelim}
-- Extract the field value info from text item 2 of recInStr
set textItem2 to text item 2 of recInStr
set valueData to text 1 thru valDataLen(textItem2) of textItem2
-- Bolt this onto the first text item of recOutStr and the delimiter
set recOutStr to text item 1 of recOutStr & labelDelim & valueData
set AppleScript's text item delimiters to {""}
-- recOutStr now represents a single-item record consisting of
-- the required label and its value from the original record
-- Correct its overall-data-length component
set recData to text 21 thru -1 of recOutStr
set recOutStr to (text 1 thru 16 of recOutStr) &
numAs4bytes(recData's length) & recData
-- Coerce the string to record, coerce that to list,
-- and extract the value therefrom
return item 1 of (recOutStr as record as list)
end extract_record_field
-- Convert an integer to a 4-byte value
-- that can be included in a string
on numAs4bytes(n)
set binaryStr to ""
repeat with i from 4 to 1 by -1
set binaryStr to binaryStr & (ASCII character (n mod (256 ^ i) div
(256 ^ (i - 1))))
end repeat
return binaryStr
end numAs4bytes
-- Determine how many characters are needed
-- from text item 2 of the original record string
on valDataLen(textItem2)
-- Start with the 4 or five characters to the end of the type ID
if character 1 of textItem2 is (ASCII character 0) then
set i to 5
else
set i to 4
end if
-- Read the length of the data from the next 4 bytes
set len to 0
repeat 4 times
set i to i + 1
set len to len * 256 + (ASCII number (character i of textItem2))
end repeat
-- Return the result + the length of the type and length info
return i + len
end valDataLen
set usrfRecord to usrf({"a", "Whoosh", "serial number", 75757575, "b",
{fred:{1, 2, 3, 4, {missing value}}}})
extract_record_field(usrfRecord, "serial number")
NG