Re: Getting the labels of a record
Re: Getting the labels of a record
- Subject: Re: Getting the labels of a record
- From: LE STANG Jean-Baptiste <email@hidden>
- Date: Sun, 9 Mar 2003 10:48:16 +0100
OK thanks for the answers, I'll try all the given advices.
JB
Le samedi, 8 mars 2003, ` 18:52 Europe/Paris, has a icrit :
Emmanuel wrote:
At 2:09 PM +0100 08/03/03, LE STANG Jean-Baptiste wrote:
>I'm looking for a way to read the names of labels in a record. Does
>anyone know how to do it?
I don't think there is any. If there were one, that would simplify
much some of my scripts.
Yup, the only "clean" way is through an app and osax that know how to
manipulate a record's internal structures; e.g. the RecordAccess osax
(OS9-only).
The only other way is to hack it; e.g. see the HashLib library I wrote
(and prompty abandoned) a couple years ago, which you can probably
find on ScriptBuilders. That was an early attempt to use records as if
they were hash arrays, on account of AS not having a hash array
datatype of its own. Probably a bit hairy to look at, but you might
find it useful to pull apart and see how it worked. Despite being the
wrong solution to the problem, it was quite robust and did what it was
supposed to do.
Still I can think of one or two situations where manipulating records
is pretty much inescapable, e.g. extracting tag attributes from XML
parsed by XML Tools (it converts them into records, making them a pain
to manipulate). So here's a "faster" version of the 'extract keys'
command I wrote for HashLib:
======================================================================
script _coerceToStringModule
on _getCDTSOffsets()
try
{a:0} as boolean --[hacky trick]
error "a record-to-boolean coercion is present." number 100
on error eMsg number -1700
end try
set oldTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to "{a:0}"
set textFrom to (eMsg's first text item's length) + 4
set textTo to -(eMsg's second text item's length) - 2
set AppleScript's text item delimiters to oldTID
return {textFrom, textTo}
end _getCDTSOffsets
on coerceToString(theData)
try
set {textFrom, textTo} to _getCDTSOffsets()
try
{a:theData} as boolean --[hacky trick]
error "a record-to-boolean coercion is present." number
[NO-BREAK]100
on error eMsg number -1700
return eMsg's text textFrom thru textTo
end try
on error eMsg number eNum
error "Couldn't coerce to string: " & eMsg number eNum
end try
end coerceToString
end script
on _valueAsString(val)
if {val's class} is in {boolean, integer, real} then
return (val as string)
else if {val's class} is in {string, Unicode text} then
return ("\"" & val & "\"")
else -- anything else gets the full stringify treatment
return (_coerceToStringModule's coerceToString(val))
end if
end _valueAsString
-------
on _getFirstOffset(theString, findString) -- (faster than Standard
[NO-BREAK]Addition's offset)
try
set oldTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to findString
count of theString's first text item
if result is theString's length then
set theOffset to 0
else
set theOffset to result + 1
end if
set AppleScript's text item delimiters to oldTID
return theOffset
on error eMsg number eNum
error "Can't get offset: " & eMsg number eNum
end try
end _getFirstOffset
on _parseBarDelimitedKeyString(str)
set str to str's text 2 thru -1
set endOfKey to false
set theKey to ""
repeat until endOfKey
set char to str's first character
if char is "\\" then
set theKey to theKey & str's second character
set str to str's text 3 thru -1
else if char is "|" then
set endOfKey to true
else
set theKey to theKey & char
set str to str's text 2 thru -1
end if
end repeat
return theKey
end _parseBarDelimitedKeyString
-------
--PUBLIC
on extractRecordKeys(theRecord)
if theRecord's class is not record then error "Not a record."
[NO-BREAK]number 200
(*Notes on next line:
- 3-chars padding to prevent error when trimming last
[NO-BREAK]'property' substring from string [a bit hacky, but quicker
[NO-BREAK]than doing the comma-space trim in an 'if propertyIndex is
[NO-BREAK]less than count of valueLengths' block]
- cTS() claims to return a string (unkown if this means ASCII
[NO-BREAK]string or international text); value returned chokes
[NO-BREAK]Standard Additions' offset command unless explicitly
[NO-BREAK]coerced to int. text beforehand; no idea why. In any case,
[NO-BREAK]TID-based getFirstOffset() seems to give a worthwhile speed
[NO-BREAK]improvement, so probably best just to keep using that.
*)
set propertiesString to (text 2 thru -2 of _coerceToStringModule's
[NO-BREAK]coerceToString(theRecord)) & " "
set keyList to {}
set valueList to theRecord as list
repeat with valRef in valueList
set valueLength to count of _valueAsString(valRef's contents)
if propertiesString's first character is "|" then
set theKey to _parseBarDelimitedKeyString(propertiesString)
set endOfKeyOffset to (1 + (count of theKey) + 1)
set keyList's end to theKey
else
set endOfKeyOffset to _getFirstOffset(propertiesString, ":")
[NO-BREAK]- 1
set keyList's end to text 1 thru endOfKeyOffset of
[NO-BREAK]propertiesString
end if
set propertiesString to propertiesString's text (endOfKeyOffset
[NO-BREAK]+ 2 + valueLength + 2) thru -1
end repeat
return keyList
end extractRecordKeys
-------
--TEST
tell application "Finder" to get item 1 of startup disk
set theRecord to {foo:"bar", c:result, bar:4.53453E-7,
[NO-BREAK]|ba-z|:{wibble:1}, |foo:\\\\ \|bar|:false, fff:date
[NO-BREAK]"Tuesday, October 1, 2002 12:00:00 am", |month|:March,
[NO-BREAK]|class|:class}
extractRecordKeys(theRecord)
--> {"foo", "c", "bar", "ba-z", "foo:\\\\ |bar", "e, fff", "month",
[NO-BREAK]"class"}
======================================================================
Uses a Richard23-style "scrunch values to string" hack (equivalent to
using Smile's "display" command), and its key-parsing routine is quite
solid (a simple 'find offset of ":"' will trip on keys enclosed in
pipes). Performance should be tolerable, though could probably be
speeded up by replacing the coerceToString bit with a call to Smile's
'display' command if that's an option. But it's a hack, so I make no
guarantees it'll work, etc.
However, if all you're looking for is an easy way to store values by a
text-based key then I'd suggest using something like my
AssociativeArray library. Much nicer than mucking about with this kind
of stuff.
HTH
has
--
http://www.barple.pwp.blueyonder.co.uk -- The Little Page of
AppleScripts
_______________________________________________
applescript-users mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/applescript-users
Do not post admin requests to the list. They will be ignored.
_______________________________________________
applescript-users mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/applescript-users
Do not post admin requests to the list. They will be ignored.