Re: interesting discovery (trying to get record labels as strings)
Re: interesting discovery (trying to get record labels as strings)
- Subject: Re: interesting discovery (trying to get record labels as strings)
- From: email@hidden
- Date: Mon, 3 Dec 2001 02:14:36 EST
OK, I can't handle this anymore! usrf! Raw contents of Apple Event Manager
records! AssociativeLib script objects! Aaarrgghh!!!! I'm too concrete for
such things. I like text. Text will still be around in 50 years. None of the
other stuff will be.
The *real* fix to the need for an efficient data structure *must* come from
Apple. Anything else will be slow and clunky.
Here is how I solved the "lack of hash tables" dilemma. I started with the
format of the posted_data which a CGI receives from a form post (a=1&b=2&c=3,
URL encoded). I then built several handlers to let me use that structure to
emulate hash tables. The system has proven to be very reliable, very fast,
and very flexible.
And the posted_data format is a damned efficient way to store data in a real
or pseudo-database. I simply write the data to text files (that's another set
of handlers) and access it that way. It is, hands down, the fastest flat file
database structure on the Mac. I have tried Valentina, tableserver, FileMaker
Pro, and others, and nothing compares for pure speed. I have a ten thousand
record and growing, searchable, multi-user, dynamic pseudodatabase
implemented using this technique. It's fabulous, and I can access and edit
the data with BBEdit when/if I need to. You can't do that with script objects
or records.
My big (huge, overwhelming) concern is that there is currently no way to
implement this in OSX, since it depends on Tanaka's osax (a MacOS classic
scripting addition). I think I saw a post about how to access classic osaxen
from OSX scripts. Can someone verify that/provide syntax? Even still, the
functionality of Tanaka's osax really needs to be provided natively in OSX.
Even an encode/decode URL function would prove very helpful.
I did some last minute renaming of handlers and variables, so I hope nothing
broke.
-- This script creates a simple data structure and then manipulates it
-- you must have Tanaka's osax version 2.01 or later installed
set sampleData to {{"First Name", "Jeff"}, {"emailaddress", "jwbaumann@aol.
com"}}
set rawPost to my LRpackCGI(sampleData)
display dialog rawPost -- this is the form that data arrives in from form
posts
set pairedList to my LRparseCGIargs(rawPost)
set firstName to my LRlookupFieldValue("First Name", pairedList)
display dialog firstName
set email to my LRextractFieldValue("emailaddress", rawPost, true)
display dialog email
set fieldnames to {"First Name", "emailaddress"}
set fieldValues to my LRlookupFieldValues(fieldnames, pairedList, "")
try
display dialog fieldValues as integer -- this WILL error
on error errmsg
display dialog text 12 thru -17 of errmsg as string
end try
-- notice how this next one fails! fieldnames must be URL-encoded first
-- solution is to use "emailaddress" as field name, not "email address"
-- emailaddress = MT encode URL "emailaddress"
-- the value of the TIDs approach is speed
set fieldValues to my LRextractFieldValues(fieldnames, rawPost)
try
display dialog fieldValues as integer
on error errmsg
display dialog text 12 thru -17 of errmsg as string
end try
set rawPost to my LRreplaceFieldValue(rawPost, "First Name", "Billy Bob",
true)
set rawPost to my LRreplaceFieldValue(rawPost, "emailaddress",
"email@hidden", false)
set parsedPost to my LRparseCGIargs(rawPost)
try
display dialog parsedPost as integer -- this WILL error
on error errmsg
display dialog text 12 thru -17 of errmsg as string
end try
--------------------- Pseudo Hash Table -------------------------------
(* Copyright Notice:
These handlers may be used by anyone for any purpose, with the following
exceptions
1) The code may not be altered without altering the names of the handlers
(my handler name means MY code).
2) The code may not be used in any programming, application, or
implementation
designed for the transfer of money, absent a licensing agreement with
me.
*)
on LRparseCGIargs(rawPost)
set parsedArgs to {}
try
set parsedArgs to MT Parse CGI rawPost with field name
on error --
end try
return parsedArgs
end LRparseCGIargs
on LRlookupFieldValue(desiredField, listOfPairedLists)
set fieldValue to ""
set desiredField to desiredField as string
try
if desiredField is in (listOfPairedLists as string) then
repeat with k from 1 to (length of listOfPairedLists)
if item 1 of (item k of listOfPairedLists) is equal to
desiredField then
copy (item 2 of (item k of listOfPairedLists)) to
fieldValue
return fieldValue
end if
end repeat
end if
end try
return fieldValue
end LRlookupFieldValue
on LRlookupFieldValues(desiredFields, listOfPairedLists, defaultValue)
set fieldValues to {}
repeat with desiredField in desiredFields
set fieldValue to my LRlookupFieldValue(desiredField,
listOfPairedLists)
if fieldValue is equal to "" then copy defaultValue to fieldValue
copy fieldValue to end of fieldValues
end repeat
return fieldValues
end LRlookupFieldValues
on LRextractFieldValue(desiredField, rawPost, decodePlease)
set fieldValue to ""
if desiredField is in rawPost then
set oldTIDs to AppleScript's text item delimiters
try
set AppleScript's text item delimiters to ("&" & desiredField &
"=")
set narrowed to (text item 2 of ("&" & rawPost & "&"))
set AppleScript's text item delimiters to "&"
if decodePlease then
set fieldValue to MT Decode URL (text item 1 of narrowed)
else
set fieldValue to text item 1 of narrowed
end if
set AppleScript's text item delimiters to oldTIDs
on error errmsg
try
set AppleScript's text item delimiters to oldTIDs
on error
set AppleScript's text item delimiters to ""
end try
end try
end if
return fieldValue
end LRextractFieldValue
on LRextractFieldValues(desiredFields, rawPost)
set fieldValues to {}
repeat with desiredField in desiredFields
copy (my LRextractFieldValue(desiredField, rawPost, false)) to end of
fieldValues
end repeat
return fieldValues
end LRextractFieldValues
on LRreplaceFieldValue(rawPost, fieldToModify, newValue, encodePlease)
if encodePlease then
set fieldToModify to MT Encode URL fieldToModify
set newValue to MT Encode URL newValue
end if
if fieldToModify is in rawPost then
set oldValue to my LRextractFieldValue(fieldToModify, rawPost, false)
set delim1 to fieldToModify & "=" & oldValue
set delim2 to fieldToModify & "=" & newValue
set processedPost to my LRreplaceString(rawPost, delim1, delim2)
end if
return processedPost
end LRreplaceFieldValue
on LRpackCGI(pairedList)
try
set packedList to MT Pack CGI pairedList
on error
set packedList to "An+Error=Occured&handler=packCGI"
end try
return packedList
end LRpackCGI
------------ this is a helper handler ---------
on LRreplaceString(src, oldString, newString)
set newsrc to src
try
set oldDelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to oldString
set srcList to text items of src as list
set AppleScript's text item delimiters to newString
set newsrc to srcList as string
set AppleScript's text item delimiters to oldDelims
on error
try
set AppleScript's text item delimiters to oldDelims
on error
set AppleScript's text item delimiters to {""}
end try
end try
return newsrc
end LRreplaceString
-----------------------------------
Jeff Baumann
email@hidden
www.linkedresources.com
In a message dated 12/2/01 6:41:54 PM, John W Baxter wrote:
>
At 13:13 -0700 12/2/2001, Michelle Steiner wrote:
>
>On 12/2/01 11:23 AM, has <email@hidden> wrote:
>
>
>
>>This just throws an error, as you'd expect. However, try this:
>
>>
>
>> {{a:1}} as string
>
>>
>
>>and the results are _much_ more interesting. Try it and see. (Though if it
>
>>doesn't generate a lot of seemingly nonsensey stuff, let me know what
>
>>version of AS you're on [I'm on 1.3.7] as there's not much point pursuing
>
>>this if it won't work everywhere.)
>
>
>
>with AS 1.6, using {{hello:65}} as string I get
>
>
>
>--> " usrflist\" TEXT hellolong A"
>
>
>
>The A at the end corresponds to ascii 65.
>
>
>
>Even more interestingly: {{hello:"goodbye"}} as string
>
>
>
>--> " usrflist& TEXT helloTEXT goodbye"
>
>
>
>And then there's this: {{hello:{65, 66}}} as string
>
>
>
>--> " usrflist> TEXT hellolist
>
> long Along B"
>
>
>
>Or this: {{hello:{"one", "two"}}} as string
>
>
>
>--> " usrflist> TEXT hellolist
>
> TEXT oneTEXT two"
>
>
>
>
AppleScript puts items into a record in two ways (not helpfully, although I
>
think helpfulness was the original intent). It is working within the
>
constraints of the Apple Event Manager record type, which is a list keyed
>
by the usual four-byte codes ("oapp" and all the others we toss around
>
here), with a value associated with each key which can be pretty much
>
anything which can be represented as an AppleScript object.
>
>
Item keys which AppleScript "knows" as keywords use the known four byte code.
>
Other item keys are stuffed into the item with the key "usrf" ("user
>
fields", I think). The value of the "usrf" item is an Apple Event Manager
>
list (at least when the record is packed up and shipped in an Apple
>
event...it could be an AppleScript internal list internally). The list
>
alternates key values (as type TEXT, the name one gives the item in the
>
record..."hello" in the closest example above) with values (as whatever
>
they are (the list which contains two items of TEXT in the same example)).
>
>
It is trivial to build these things so that AppleScript can understand
>
them. It's also trivial to break them apart. Unfortunately, it's not
>
trivial to do either thing arbitrarily in AppleScript, which has only the
>
published ways to access items in records.
>
>
I had a reasonably favorable response a few months ago when I suggested to
>
Chris Nebel that
>
1. AppleScript forget about special casing record keys it knows about, for
>
making new records (it obviously has to deal with existing ones); and
>
2. provide access to the remaining one thing in a record, the "usrf" list.
>
>
But...there is no reason to expect to see the features any time soon, if at
>
all.
>
>
You can partly achieve #1 today... the name |application| on a record item
>
places that record into the "usrf" list, not up in the known keywords part
>
of the underlying record. But then you're stuck remembering that the two |
>
characters are part of the name. |application| is just an example; I could
>
just as well have said |run|.
>
>
Given 2, one could learn what items are in a record, could build an
>
arbitrary record on the fly (rather than at compile time), etc.
>
>
Someone could write an OSAX which hands over the "usrf" list from a record,
>
probably with the non-usrf items stuck onto the end of the list, or stuffs
>
a list...after checking for suitability...into the "usrf" field of a new
>
record and hands back the record. Aside from the OSAX boilerplate, it
>
would be about one screen of code to hold both functions. Given that OSAX,
>
everything else I've recently seen talked about could be done in
>
AppleScript code, with the following cavaets:
>
>
a. AppleScript would tend to move items named with known keywords out of
>
the "usrf" list if it had any reason to rebuild the list (I ran into this
>
in the mid-1990s when playing with building arbitrary AppleScript records
>
in Frontier and handing them to AppleScript).
>
>
b. And if a happens, AppleScript will change the case of the item name to
>
match what it "knows" (or it would do that in the mid-1990s).
>
>
--John
>
--
>
John Baxter email@hidden Port Ludlow, WA, USA