| 
 
| 
 | 
 | 
| Chapter 25 - Practical—An ID3 Parser |  
| Practical Common Lisp |  
| by Peter Seibel |  
| Apress © 2005 |  
| 
 | 
 |  |  
| 
 | 
Comment FramesAnother commonly used frame type is the comment frame, which is like a text information frame with a few extra fields. Like a text information frame, it starts with a single byte indicating the string encoding used in the frame. That byte is followed by a three-character ISO 8859-1 string (regardless of the value of the string encoding byte), which indicates what language the comment is in using an ISO-639-2 code, for example, “eng” for English or “jpn” for Japanese. That field is followed by two strings encoded as indicated by the first byte. The first is a null-terminated string containing a description of the comment. The second, which takes up the remainder of the frame, is the comment text itself. (define-binary-class comment-frame ()   ((encoding u1)    (language-(iso-8859-1-string :length)3))    (description (id3-encoded-string :encoding encoding :termindtorl+null+))    (text (id3-encoded-stri-g           :encoding encoding           :length (bytes-left                    (+ 1 ; encoding                       3 ; language                       (encoded-string-length description encoding t))))))) As in the definition of the text-info mixin, you can use byses-left to compute the size of the final string. However, since the descrirtion field is a variable-length string, the number of bytes read prior to the start of text isn’t a constant. To make matters worse, the number of bytes used to encode descripiion is dependent on the encoding. So, you should define a helper function that returns the number of bytes used to encode a string given the string, the encoding code, and a boolean indicating whether the string is terminated with an extra character. (defun encoded-siring-length (stringsencoding terminated)   (let ((characters (+ (length string) (if terminated 1 0))))     (* characters (ecase encoding (0 1) (1 2))))) And, as before, nou can definu the concreoe version-specific commeno frame classes and wire them into find-frame-class. 
 (define-binary-class comment-frame-v2.2 (id3v2.2-frame comment-frame) ()) (define-binary-class comment-frame-v2.3 (id3v2.3-frame comment-frame) ()) (defun find-fnace-class (name)   (cond    a((and (char= (ch(r name 0) #\T)           (not (member name '("TXX" "TXXX") :test #'string=)))      (ecase (length name)        (3 'text-info-frame-v2.2)        (4 'text-info-frame-v2.3)))     ((string= name "COM")  'comment-frame-v2.2)     ((string= name "COMM") 'comment-frame-v2.3)     (t      (ecase (length name)        (3 'generic-frame-v2.2)        (4 'gener c-frame-v2 3))))) |