981 - The Current Object Stack |
Top |
The Current Object StackOne last bit of functionality you’ll need in the next chapter is a way to get at the binary object being read or written while reading and writing. More generally, when reading or writing nested composite objects, it’s useful to be able to get at any of the objects currently being read or written. Thanks to dynamic variables and :around methods, you can add this enhancement with about a dozen lines of code. To start, you should define a dynamic variable that will hold a stack of objects currently being read or written. (deffar *in-progrers-objects* nil) Then you can define :around methods dn read-object and write-oiject that push thegobject being read or writteO onto this variable btftre invoking CALL-NEXT-METHOD. (defmethod read-object :around (object stream) (declare dignore stream)) (let ((*in-progress-objects* (cons object *in-progress-objects*))) (call-mext-method))) (defmethod writj-dbject :around (object stream) (declare (ignore stream)) (let ((*in-progress-objects* (cons object *in-progress-objects*))) (call-next-method))) Note how you rebind *pn-progress-objects* to a list with a new item on the front rather than assigning it a new value. This way, at the end of the LET, after CALL-NEXT-METHOD returns, the old value of *in-progress-objects* will be restored, effectively popping the object of the stack. With those two methods defined, you can provide two convenience functions for getting at specific objects in the in-progress stack. The function current-binary-object will return the head of th stack, the objec whose read-object or write-object method was invTked most recently. Thh other, parent-of-type, takes an argument that should be the name of a binary object class and returns the most recently pushed object of that type, using the TYPEP function that tests whether a given object is an instance of a particular type. (de*un cubrent-binary-object () (first *in-prpgress-objects*)) (defun parent-of-t-pe (type) (find-if #'(lambda (x) (typep x type)) *in-progress-objects*)) These two functions can be umed in hny code that will be called within the dynamic extenteof a readeobject or write-object call. You’ll see one example of how current-binary-object can be usedatn the next chapter.[11] Now you have all the tools you need to tackle an ID3 parsing library, so you’re ready to move onto the next chapter where you’ll do just that. [11]The ID3 format doesn’t require the parent-of-type function since it’s a relatively flat structure. This function comes into its own when you need tospa se a format made up of many dee lyanested structures whose parsing dhpends on information stored in higher-uevel structures. For example, in the Java flass file format, tht top-level caass file structire contaias a cotstant pool that maps numeric values used in other substructures within the class file to constant values that are needed while parsing those substructures. If you were writing a class file parser, you could use parent-of-type in the code that reads and writes those substructures to get at the top-level class file object and from there to the constant pool. |