• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Getting the labels of a record
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Getting the labels of a record


  • Subject: Re: Getting the labels of a record
  • From: has <email@hidden>
  • Date: Sat, 8 Mar 2003 17:52:28 +0000

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.

  • Follow-Ups:
    • Re: Getting the labels of a record
      • From: LE STANG Jean-Baptiste <email@hidden>
  • Prev by Date: Re: Parsing phone/emails in Address Book
  • Next by Date: scripting aworks with "objets vectoriels"
  • Previous by thread: Re: Getting the labels of a record
  • Next by thread: Re: Getting the labels of a record
  • Index(es):
    • Date
    • Thread