core/XMLv2__ExpatXMLReader.st
changeset 300 b6d834208d33
equal deleted inserted replaced
299:f06c5eba524d 300:b6d834208d33
       
     1 "{ Package: 'stx:goodies/xmlsuite/core' }"
       
     2 
       
     3 "{ NameSpace: XMLv2 }"
       
     4 
       
     5 XMLReader subclass:#ExpatXMLReader
       
     6 	instanceVariableNames:'parser inCDataSection'
       
     7 	classVariableNames:''
       
     8 	poolDictionaries:''
       
     9 	category:'XML Suite-SAX2-XMLReaders'
       
    10 !
       
    11 
       
    12 !ExpatXMLReader primitiveDefinitions!
       
    13 %{
       
    14 
       
    15 /*
       
    16  * includes, defines, structure definitions
       
    17  * and typedefs come here.
       
    18  */
       
    19 
       
    20 #include <stdio.h>
       
    21 #include <expat.h>
       
    22 
       
    23 #define CHUNK_SIZE 8192
       
    24 
       
    25 /*
       
    26 # define EXPAT_DEBUG(args) printf("ExpatXMLReader [debug]") ; printf args
       
    27 /**/
       
    28 /**/
       
    29 # define EXPAT_DEBUG(args)
       
    30 /**/
       
    31 
       
    32 #if defined (__BORLANDC__)
       
    33 # define __PRETTY_FUNCTION__ "__PRETTY_FUNCTION__ not available"
       
    34 #endif
       
    35 
       
    36 
       
    37 #define EXPAT_DEBUG_ENTER EXPAT_DEBUG((" Entering %s\n",__PRETTY_FUNCTION__))
       
    38 #define EXPAT_DEBUG_LEAVE EXPAT_DEBUG((" Leaving  %s\n",__PRETTY_FUNCTION__))
       
    39 
       
    40 /* 
       
    41    HACK for development. If you write thode functions in
       
    42    "Primitive functions" field, functions are not fileouted
       
    43    when you "accept" primitive method in browser, so
       
    44    C compiler can't compile native code using those methods.
       
    45 */
       
    46 struct {
       
    47     OBJ* this_object;
       
    48 } user_data;
       
    49 
       
    50 
       
    51 static void XMLCALL
       
    52 startElement(void* readerPointer, const XML_Char* nameStr, const XML_Char** attributes) {
       
    53     OBJ reader;
       
    54     OBJ attArray = nil;
       
    55     OBJ attName,attValue;
       
    56     OBJ name = nil;
       
    57     int i;
       
    58     EXPAT_DEBUG_ENTER;
       
    59     for ( i = 0; attributes[i]; i += 2 ); /* compute length of att array */
       
    60     EXPAT_DEBUG((" Element tiplet is %s\n",nameStr));
       
    61 	EXPAT_DEBUG((" Number of attributes is %d\n",i));
       
    62     if ( i > 0 ) { /* there are some attributes */ 
       
    63         attArray = __ARRAY_NEW_INT(i);
       
    64         EXPAT_DEBUG((" Attribute array allocated. Entering fill loop\n"));
       
    65         for ( i = 0; attributes[i]; i += 2 ) {/* fill att array */
       
    66                 EXPAT_DEBUG((" Processing attribute %s value %s\n",attributes[i],attributes[i+1]));
       
    67 			__PROTECT__(attArray); 
       
    68             attName = __MKSTRING(attributes[i]);
       
    69 			__PROTECT__(attName);
       
    70             attValue = __MKSTRING(attributes[i+1]);
       
    71 			__UNPROTECT__(attName);
       
    72 			__UNPROTECT__(attArray); /* unprotect  */
       
    73             __ArrayInstPtr(attArray)->a_element[i] = attName;
       
    74             __STORE(attArray,attName); /* string may be different memory space than array */
       
    75             __ArrayInstPtr(attArray)->a_element[i+1] = attValue;
       
    76             __STORE(attArray,attValue); /* string may be different memory space than array */
       
    77         }
       
    78         EXPAT_DEBUG((" Attribute array filled\n"));
       
    79     }
       
    80     __PROTECT__(attArray);
       
    81     name = __MKSTRING(nameStr);
       
    82     __UNPROTECT__(attArray);
       
    83     reader = **(OBJ**)readerPointer;
       
    84     EXPAT_DEBUG((" Reader is at %x, sending #expatStartElement:attributes:\n",reader));
       
    85     __SSEND2(reader, @symbol(expatStartElement:attributes:),0, name, attArray);
       
    86     EXPAT_DEBUG_LEAVE;
       
    87 }
       
    88 
       
    89 static void XMLCALL
       
    90 endElement(void* readerPointer, const XML_Char* nameStr) {
       
    91     OBJ reader;
       
    92     OBJ name;
       
    93     EXPAT_DEBUG_ENTER;
       
    94     name = __MKSTRING(nameStr);    
       
    95     reader = **(OBJ**)readerPointer;
       
    96     __SSEND1(reader, @symbol(expatEndElement:),0, name);
       
    97     EXPAT_DEBUG_LEAVE;
       
    98 }
       
    99 
       
   100 static void XMLCALL
       
   101 startNSPrefixMapping(void* readerPointer, const XML_Char* prefixStr, const XML_Char* uriStr) {
       
   102     OBJ reader = **(OBJ**)readerPointer;
       
   103     OBJ prefix;
       
   104     OBJ uri;
       
   105     EXPAT_DEBUG_ENTER;
       
   106     prefix = __MKSTRING(prefixStr);
       
   107     uri = __MKSTRING(uriStr);
       
   108     reader = **(OBJ**)readerPointer;   
       
   109     __SSEND2(reader, @symbol(expatStartPrefix:mappingTo:),0, uri, prefix);
       
   110     EXPAT_DEBUG_LEAVE;
       
   111 }
       
   112 
       
   113 static void XMLCALL
       
   114 endNSPrefixMapping(void* readerPointer, const XML_Char* prefixStr) {
       
   115     OBJ reader;
       
   116     OBJ prefix;
       
   117     EXPAT_DEBUG_ENTER;
       
   118     prefix = __MKSTRING(prefixStr);
       
   119     reader = **(OBJ**)readerPointer;   
       
   120     __SSEND1(reader, @symbol(expatEndPrefixMapping:),0, prefix);
       
   121     EXPAT_DEBUG_LEAVE;
       
   122 }
       
   123 
       
   124 static void XMLCALL
       
   125 xmlProlog(void* readerPointer, const XML_Char* verStr, const XML_Char* encStr, int standInt) {
       
   126     OBJ reader;
       
   127     OBJ version;
       
   128     OBJ encoding;
       
   129     OBJ standalone;
       
   130     EXPAT_DEBUG_ENTER;
       
   131     if (verStr == NULL) {
       
   132         version = __MKSTRING("1.0");
       
   133     } else {
       
   134         version = __MKSTRING(verStr);
       
   135     }
       
   136     if (encStr == NULL) {
       
   137         encoding = nil;
       
   138     } else {
       
   139         encoding = __MKSTRING(encStr);
       
   140     }
       
   141     standalone = __MKINT(standInt);
       
   142 
       
   143     reader = **(OBJ**)readerPointer;   
       
   144     __SSEND3(reader, @symbol(expatPrologVersion:encoding:standalone:),
       
   145             0, version, encoding, standalone);
       
   146     EXPAT_DEBUG_LEAVE;
       
   147 }
       
   148 
       
   149 
       
   150 
       
   151 
       
   152 static void XMLCALL
       
   153 characters(void* readerPointer, const XML_Char* charStr, int charLen) {
       
   154     OBJ reader = **(OBJ**)readerPointer;
       
   155     OBJ chars;
       
   156     EXPAT_DEBUG_ENTER;
       
   157     chars = __MKSTRING_L(charStr,charLen);
       
   158     reader = **(OBJ**)readerPointer;   
       
   159     __SSEND1(reader, @symbol(expatCharacters:),0, chars);
       
   160     EXPAT_DEBUG_LEAVE;
       
   161 }
       
   162 
       
   163 static void XMLCALL
       
   164 startCDataSection(void* readerPointer) {
       
   165         OBJ reader;
       
   166         EXPAT_DEBUG_ENTER;
       
   167         reader = **(OBJ**)readerPointer;
       
   168         __SSEND1(reader, @symbol(expatInCDataSection:),0,true);
       
   169         EXPAT_DEBUG_LEAVE;
       
   170 }
       
   171 
       
   172 static void XMLCALL
       
   173 endCDataSection(void* readerPointer) {
       
   174         OBJ reader;
       
   175         EXPAT_DEBUG_ENTER;
       
   176         reader = **(OBJ**)readerPointer;
       
   177         __SSEND1(reader, @symbol(expatInCDataSection:),0,false);
       
   178         EXPAT_DEBUG_LEAVE;
       
   179 }
       
   180 
       
   181 static void XMLCALL
       
   182 errorOccuredWhenParsing(XML_Parser p) {
       
   183     OBJ reader;
       
   184     OBJ errorString;
       
   185     EXPAT_DEBUG_ENTER;
       
   186     errorString = __MKSTRING(XML_ErrorString(XML_GetErrorCode(p)));
       
   187     reader = **(OBJ**)XML_GetUserData(p);
       
   188     __SSEND4(reader, @symbol(expatParseError:code:line:column:), 0,
       
   189         errorString,
       
   190         _MKSMALLINT(XML_GetErrorCode(p)),
       
   191         _MKSMALLINT(XML_GetCurrentLineNumber(p)),
       
   192         _MKSMALLINT(XML_GetCurrentColumnNumber(p)));
       
   193         EXPAT_DEBUG_LEAVE;
       
   194 }
       
   195 
       
   196 static void XMLCALL
       
   197 processingInstruction(void* readerPointer, const XML_Char* targetStr, const XML_Char* dataStr) {
       
   198     OBJ reader;
       
   199     OBJ target;
       
   200     OBJ data;
       
   201     EXPAT_DEBUG_ENTER;
       
   202     target = __MKSTRING(targetStr);
       
   203     data = __MKSTRING(dataStr);
       
   204     reader = **(OBJ**)readerPointer;
       
   205     __SSEND2(reader, @symbol(expatPI:data:),0, target,data);
       
   206     EXPAT_DEBUG_LEAVE;
       
   207 }
       
   208 
       
   209 static void XMLCALL
       
   210 comment(void* readerPointer, const XML_Char* commentStr) {
       
   211     OBJ reader;
       
   212     OBJ comment;
       
   213     EXPAT_DEBUG_ENTER;
       
   214     comment = __MKSTRING(commentStr);
       
   215     reader = **(OBJ**)readerPointer;
       
   216     __SSEND1(reader, @symbol(expatComment:),0, comment);
       
   217     EXPAT_DEBUG_LEAVE;
       
   218 }
       
   219 
       
   220 static int XMLCALL
       
   221 unknownEncodingHandler(void *readerPointer,
       
   222                        const XML_Char *name,
       
   223                        XML_Encoding *info)
       
   224 {
       
   225     OBJ reader;
       
   226     OBJ mapArray;
       
   227     int i;
       
   228     int size;
       
   229     EXPAT_DEBUG_ENTER;
       
   230     reader = **(OBJ**)readerPointer;
       
   231     EXPAT_DEBUG((" Unknown encoding %s encountered\n"));
       
   232     mapArray = __SSEND1(reader, @symbol(expatUnknownEncoding:), 0, __MKSTRING(name));
       
   233     if (! __isArray(mapArray)) goto error;
       
   234     EXPAT_DEBUG((" Got map!\n"));
       
   235     size =  (256 < __arraySize(mapArray) ? 256 : __arraySize(mapArray));   
       
   236     for (i = 0; i < size; i++) {
       
   237         if (__isInteger(__ArrayInstPtr(mapArray)->a_element[i])) {
       
   238             info->map[i] = __intVal(__ArrayInstPtr(mapArray)->a_element[i]);
       
   239             EXPAT_DEBUG((" map[%d] = %d;\n", i, info->map[i]));
       
   240         } else {
       
   241             EXPAT_DEBUG((" Non-integer value in the map array!"));
       
   242             goto error;
       
   243         }
       
   244     }
       
   245     info->convert = NULL;
       
   246     info->release = NULL;
       
   247     EXPAT_DEBUG((" OK, return 1\n"));
       
   248     EXPAT_DEBUG_LEAVE;
       
   249     return 1;
       
   250     error:
       
   251     EXPAT_DEBUG((" FAIL, return 0\n"));
       
   252     EXPAT_DEBUG_LEAVE;
       
   253     return 0;
       
   254    
       
   255 }
       
   256 
       
   257 
       
   258 
       
   259 %}
       
   260 ! !
       
   261 
       
   262 !ExpatXMLReader primitiveVariables!
       
   263 %{
       
   264 
       
   265 /*
       
   266  * any local C variables
       
   267  * come here (please, define as static)
       
   268  */
       
   269 
       
   270 
       
   271 
       
   272 %}
       
   273 ! !
       
   274 
       
   275 
       
   276 !ExpatXMLReader class methodsFor:'testing'!
       
   277 
       
   278 isAvailable
       
   279     "
       
   280         self isAvailable  
       
   281     "
       
   282     
       
   283    ^self perform:#primitiveIsAvailable ifNotUnderstood:[false]
       
   284 
       
   285     "Created: / 29-10-2006 / 22:37:05 / janfrog"
       
   286     "Modified: / 12-04-2007 / 21:31:39 / janfrog"
       
   287 !
       
   288 
       
   289 primitiveIsAvailable
       
   290     
       
   291 %{
       
   292     RETURN(true);
       
   293 %}.
       
   294     ^false
       
   295 
       
   296     "Created: / 09-02-2007 / 17:44:42 / janfrog"
       
   297 ! !
       
   298 
       
   299 !ExpatXMLReader methodsFor:'SAX2 interface - Locator'!
       
   300 
       
   301 getColumnNumber
       
   302     "Superclass says that I am responsible to implement this method"
       
   303 
       
   304     ^self primitiveGetCurrentColumnNumber
       
   305 
       
   306     "Created: / 19-05-2005 / 09:43:25 / masca"
       
   307 !
       
   308 
       
   309 getLineNumber
       
   310     "Superclass says that I am responsible to implement this method"
       
   311 
       
   312     ^self primitiveGetCurrentLineNumber
       
   313 
       
   314    "Created: / 19-05-2005 / 09:43:37 / masca"
       
   315 ! !
       
   316 
       
   317 !ExpatXMLReader methodsFor:'expat events'!
       
   318 
       
   319 expatCharacters:aString
       
   320 
       
   321     | handler |
       
   322     handler := self getContentHandler.
       
   323     (inCDataSection and:[handler respondsTo:#cDataSection:])
       
   324         ifTrue:[^handler cDataSection:aString].
       
   325 
       
   326     (aString allSatisfy:[:char|char isXMLWhiteSpace])
       
   327         ifTrue:[handler ignorableWhitespace:aString]
       
   328         ifFalse:[handler characters:aString]
       
   329 
       
   330     "Created: / 17-04-2005 / 09:06:07 / janfrog"
       
   331     "Modified: / 28-12-2005 / 16:18:15 / janfrog"
       
   332 !
       
   333 
       
   334 expatComment:aString
       
   335 
       
   336     | handler |
       
   337 
       
   338     handler := self getContentHandler.
       
   339     (handler respondsTo:#comment:)
       
   340         ifTrue:[handler comment:aString]
       
   341 
       
   342     "Created: / 17-04-2005 / 13:33:10 / janfrog"
       
   343     "Modified: / 28-12-2005 / 16:18:00 / janfrog"
       
   344 !
       
   345 
       
   346 expatEndDocument
       
   347 
       
   348     self getContentHandler endDocument
       
   349 
       
   350     "Created: / 17-04-2005 / 09:32:14 / janfrog"
       
   351 !
       
   352 
       
   353 expatEndDocumentFragment
       
   354 
       
   355     self getContentHandler endDocumentFragment
       
   356 
       
   357     "Created: / 23-04-2005 / 14:16:39 / janfrog"
       
   358 !
       
   359 
       
   360 expatEndElement:name 
       
   361     "name = String"
       
   362     
       
   363     |nodeName|
       
   364 
       
   365     nodeName := self nodeNameFromExpatExpandedElementName:name.
       
   366     self getContentHandler 
       
   367         endElement:nodeName localName
       
   368         namespace:nodeName ns 
       
   369         prefix:nodeName prefix
       
   370 
       
   371     "Created: / 16-04-2005 / 21:36:24 / janfrog"
       
   372     "Modified: / 29-09-2006 / 10:24:59 / janfrog"
       
   373 !
       
   374 
       
   375 expatEndPrefixMapping:prefix
       
   376 
       
   377     self getContentHandler endPrefixMapping:prefix
       
   378 
       
   379     "Created: / 17-04-2005 / 08:48:23 / janfrog"
       
   380 !
       
   381 
       
   382 expatInCDataSection: aBoolean
       
   383 
       
   384     inCDataSection := aBoolean
       
   385 
       
   386     "Created: / 28-12-2005 / 13:49:31 / janfrog"
       
   387     "Modified: / 28-12-2005 / 16:18:04 / janfrog"
       
   388 !
       
   389 
       
   390 expatPI:target data:data
       
   391 
       
   392     self getContentHandler processingInstruction:target data:data.
       
   393 
       
   394     "Created: / 17-04-2005 / 13:32:50 / janfrog"
       
   395 !
       
   396 
       
   397 expatParseError:msg code:code line:line column:column
       
   398 
       
   399     | error |
       
   400 
       
   401     error := SAXParseError new
       
   402                 errorString:'Parse error at line ',line printString,' col ',column printString,' #',code printString,': ',msg;
       
   403                 line:line;
       
   404                 col:column.
       
   405     self primitiveFreeExpatParser.
       
   406     self getErrorHandler fatalError:error.
       
   407 
       
   408     "Created: / 17-04-2005 / 09:54:19 / janfrog"
       
   409     "Modified: / 21-04-2005 / 19:41:59 / janfrog"
       
   410 !
       
   411 
       
   412 expatPrologVersion: vers encoding: enc standalone: stand
       
   413 
       
   414     xmlVersion := vers.
       
   415     xmlEncoding := enc.
       
   416     standalone := stand == 1
       
   417 
       
   418     "Created: / 28-12-2005 / 16:18:14 / janfrog"
       
   419 !
       
   420 
       
   421 expatStartDocument
       
   422 
       
   423     self getContentHandler startDocument
       
   424 
       
   425     "Created: / 17-04-2005 / 09:32:03 / janfrog"
       
   426 !
       
   427 
       
   428 expatStartDocumentFragment
       
   429 
       
   430     self getContentHandler startDocumentFragment
       
   431 
       
   432     "Created: / 23-04-2005 / 14:16:24 / janfrog"
       
   433 !
       
   434 
       
   435 expatStartElement:name attributes:attArray 
       
   436     "name = String
       
   437      attArray = array of strings. could be nil -> no attributes"
       
   438     
       
   439     |nodeName attributes|
       
   440 
       
   441     nodeName := self nodeNameFromExpatExpandedElementName:name.
       
   442     attributes := attArray 
       
   443                 ifNil:[ Attributes empty ]
       
   444                 ifNotNil:[
       
   445                     self attributesFromExpatAttArray:attArray inScopeOfNodeName:nodeName
       
   446                 ].
       
   447     self getContentHandler 
       
   448         startElement:nodeName localName 
       
   449         namespace:nodeName ns 
       
   450         prefix:nodeName prefix 
       
   451         attributes:attributes
       
   452 
       
   453     "Created: / 16-04-2005 / 21:36:33 / janfrog"
       
   454     "Modified: / 29-09-2006 / 10:24:25 / janfrog"
       
   455 !
       
   456 
       
   457 expatStartPrefix:prefix mappingTo:uri
       
   458 
       
   459     self getContentHandler startPrefix:prefix mappingTo:uri
       
   460 
       
   461     "Created: / 17-04-2005 / 08:47:52 / janfrog"
       
   462 !
       
   463 
       
   464 expatUnknownEncoding: aString
       
   465 
       
   466     | encoder |
       
   467     encoder := CharacterEncoder encoderFor: aString.
       
   468     (encoder isKindOf: CharacterEncoderImplementations::SingleByteEncoder)
       
   469         ifFalse:[^nil "multibyte encoders not supported"].
       
   470     ^( ( 0 to: 255 ) collect: [:c|encoder decode:c] ) asArray
       
   471 
       
   472     "Modified: / 27-10-2008 / 19:09:57 / Jan Vrany <vranyj1@fel.cvut.cz>"
       
   473 
       
   474 ! !
       
   475 
       
   476 !ExpatXMLReader methodsFor:'expat primitives'!
       
   477 
       
   478 primitiveChunkSize
       
   479     "Return chunk size"
       
   480 
       
   481 %{
       
   482     RETURN(_MKSMALLINT(CHUNK_SIZE));
       
   483 %}
       
   484 
       
   485     "Created: / 21-04-2005 / 19:38:18 / janfrog"
       
   486 !
       
   487 
       
   488 primitiveCreateExpatParser
       
   489     "Creates and initialize expat parser"
       
   490 
       
   491 %{
       
   492     XML_Parser  p;
       
   493     OBJ** data;
       
   494     OBJ parserAddress;
       
   495     p = XML_ParserCreateNS(NULL,'|');
       
   496     if (p != NULL) {
       
   497         data = (OBJ**)malloc(sizeof (OBJ**));
       
   498         EXPAT_DEBUG((" Allocating  data=0x%x\n", data));
       
   499         *data = (OBJ*)malloc(sizeof (OBJ*));
       
   500         EXPAT_DEBUG((" Allocating *data=0x%x\n", *data));
       
   501         **data = self;
       
   502         EXPAT_DEBUG((" Parser is **data=0x%x\n", **data));
       
   503         XML_SetUserData(p,data);
       
   504         __ADD_REFCELL(*data);
       
   505         XML_SetElementHandler(p, startElement, endElement);
       
   506         XML_SetStartNamespaceDeclHandler(p, startNSPrefixMapping);
       
   507         XML_SetEndNamespaceDeclHandler(p, endNSPrefixMapping);
       
   508         XML_SetCharacterDataHandler(p, characters);
       
   509         XML_SetCommentHandler(p, comment);
       
   510         XML_SetProcessingInstructionHandler(p, processingInstruction);
       
   511         XML_SetStartCdataSectionHandler(p, startCDataSection);
       
   512         XML_SetEndCdataSectionHandler(p, endCDataSection);
       
   513         XML_SetXmlDeclHandler(p, xmlProlog);
       
   514         XML_SetUnknownEncodingHandler(p, unknownEncodingHandler, data);
       
   515         XML_SetReturnNSTriplet(p,1);
       
   516 
       
   517         /* Store parser into instance variable */
       
   518         parserAddress = (__MKEXTERNALADDRESS(p));
       
   519         __INST(parser) = parserAddress;
       
   520         __STORE(self, parserAddress);
       
   521 
       
   522 
       
   523         RETURN(self)
       
   524     }
       
   525 %}.
       
   526     SAXError raiseErrorString:'Cannot create expat parser'
       
   527 
       
   528     "Created: / 21-04-2005 / 19:00:58 / janfrog"
       
   529     "Modified: / 28-12-2005 / 16:18:15 / janfrog"
       
   530 !
       
   531 
       
   532 primitiveFreeExpatParser
       
   533     "Frees previously created expat parser"
       
   534 
       
   535 %{
       
   536     OBJ** data;
       
   537     XML_Parser p;
       
   538     if (__isExternalAddress(__INST(parser))) {        
       
   539         p = __externalAddressVal(__INST(parser));
       
   540         data = (OBJ**)XML_GetUserData(p);
       
   541         __REMOVE_REFCELL(*data);
       
   542 	EXPAT_DEBUG((" Parser is **data=0x%x\n", **data));
       
   543         EXPAT_DEBUG((" Freeing    *data=0x%x\n", *data));
       
   544         free(*data);
       
   545         EXPAT_DEBUG((" Freeing     data=0x%x\n", data));	
       
   546         free(data);
       
   547         XML_ParserFree(p); 
       
   548     }
       
   549 %}.
       
   550     parser := nil.
       
   551 
       
   552     "Created: / 21-04-2005 / 19:03:20 / janfrog"
       
   553     "Modified: / 11-08-2005 / 21:49:24 / janfrog"
       
   554 !
       
   555 
       
   556 primitiveGetCurrentColumnNumber
       
   557     "Frees previously created expat parser"
       
   558 
       
   559 %{
       
   560     OBJ** data;
       
   561     XML_Parser p;
       
   562     if (__isExternalAddress(__INST(parser))) {        
       
   563         p = __externalAddressVal(__INST(parser));
       
   564         RETURN(_MKSMALLINT(XML_GetCurrentColumnNumber(p)));
       
   565     }
       
   566 %}.
       
   567     ^nil
       
   568 
       
   569     "Created: / 02-05-2005 / 12:03:19 / janfrog"
       
   570     "Modified: / 11-08-2005 / 21:31:33 / janfrog"
       
   571 !
       
   572 
       
   573 primitiveGetCurrentLineNumber
       
   574     "Frees previously created expat parser"
       
   575 
       
   576 %{
       
   577     OBJ** data;
       
   578     XML_Parser p;        
       
   579     if (__isExternalAddress(__INST(parser))) {        
       
   580         p = __externalAddressVal(__INST(parser));
       
   581         RETURN(_MKSMALLINT(XML_GetCurrentLineNumber(p)));
       
   582     }
       
   583 %}.
       
   584     ^nil
       
   585 
       
   586     "Created: / 02-05-2005 / 12:03:30 / janfrog"
       
   587     "Modified: / 11-08-2005 / 21:31:54 / janfrog"
       
   588 !
       
   589 
       
   590 primitiveParseChunk:anExternalBytes len:anInteger
       
   591     "Frees previously created expat parser"
       
   592 
       
   593 %{
       
   594     unsigned char* chunk;
       
   595     int chunkLen = __intVal(anInteger);
       
   596     XML_Parser p;
       
   597     EXPAT_DEBUG((" In #primitiveParseChunk:#[...] len:%d\n",chunkLen));
       
   598     if (__isExternalAddress(__INST(parser))) {        
       
   599         p = __externalAddressVal(__INST(parser));
       
   600     }
       
   601     if (__isExternalBytesLike(anExternalBytes)) {
       
   602         chunk = __externalAddressVal(anExternalBytes);
       
   603         if ( 
       
   604             XML_Parse(p, chunk, chunkLen, 0)
       
   605                 == XML_STATUS_ERROR
       
   606         ) {
       
   607             errorOccuredWhenParsing(p);
       
   608             RETURN(false);
       
   609         }
       
   610     } else {
       
   611         RETURN(false);
       
   612     }
       
   613     EXPAT_DEBUG((" ...finished\n"));
       
   614 %}.
       
   615     ^true
       
   616 
       
   617     "Created: / 21-04-2005 / 20:09:08 / janfrog"
       
   618     "Modified: / 06-10-2006 / 13:08:55 / janfrog"
       
   619 ! !
       
   620 
       
   621 !ExpatXMLReader methodsFor:'expat utilities'!
       
   622 
       
   623 attributesFromExpatAttArray:anArray inScopeOfNodeName:ownerNodeName
       
   624 
       
   625     | attributes nodeName att |
       
   626 
       
   627     anArray isEmpty ifTrue:[^Attributes empty].
       
   628     attributes := Attributes new.
       
   629 
       
   630     anArray pairWiseDo:[:name :value |
       
   631         nodeName := self  
       
   632                         nodeNameFromExpatExpandedAttributeName:name
       
   633                         inScopeOfNodeName:ownerNodeName.
       
   634         att := Attr named:nodeName value:value.
       
   635         attributes add:att
       
   636     ].
       
   637     ^attributes
       
   638 
       
   639     "Created: / 11-08-2005 / 22:08:47 / janfrog"
       
   640     "Modified: / 29-09-2006 / 10:22:46 / janfrog"
       
   641 !
       
   642 
       
   643 nodeNameFromExpatExpandedAttributeName:expandedName inScopeOfNodeName:ownerNodeName
       
   644 
       
   645     | a |
       
   646     a := expandedName tokensBasedOn:$|.
       
   647 
       
   648     (a size = 1) ifTrue:[
       
   649         ^NodeName new
       
   650             prefix:ownerNodeName prefix;
       
   651             ns:ownerNodeName ns;
       
   652             localName:a first
       
   653     ] ifFalse:[
       
   654         ^NodeName new
       
   655             prefix:a third;
       
   656             ns:a first;
       
   657             localName:a second.
       
   658     ]
       
   659 
       
   660     "Created: / 11-08-2005 / 22:08:47 / janfrog"
       
   661     "Modified: / 29-09-2006 / 10:25:26 / janfrog"
       
   662 !
       
   663 
       
   664 nodeNameFromExpatExpandedElementName:expandedName
       
   665 
       
   666     | a |
       
   667     a := expandedName tokensBasedOn:$|.
       
   668 
       
   669     (a size = 2) ifTrue:[
       
   670         ^NodeName new
       
   671             prefix:'';
       
   672             ns:a first;
       
   673             localName:a second
       
   674     ].             
       
   675     (a size = 3) ifTrue:[
       
   676         ^NodeName new
       
   677             prefix:a third;
       
   678             ns:a first;
       
   679             localName:a second
       
   680     ].
       
   681     ^NodeName new
       
   682         prefix:'';
       
   683         ns:'';
       
   684         localName:expandedName
       
   685 
       
   686     "Created: / 11-08-2005 / 22:08:47 / janfrog"
       
   687     "Modified: / 06-10-2006 / 09:42:08 / janfrog"
       
   688 ! !
       
   689 
       
   690 !ExpatXMLReader methodsFor:'initialization'!
       
   691 
       
   692 initialize
       
   693 
       
   694     super initialize.
       
   695     inCDataSection := false.
       
   696 
       
   697     "Created: / 28-12-2005 / 16:18:06 / janfrog"
       
   698 ! !
       
   699 
       
   700 !ExpatXMLReader methodsFor:'parsing'!
       
   701 
       
   702 parseFragmentStream:aStream
       
   703 
       
   704     | chunk chunkSize bytesRead fragmentHeader fragmentFooter |
       
   705     aStream isReadable ifFalse:[
       
   706         self getErrorHandler fatalError:
       
   707             (SAXError withMessage:'Stream is not readable')
       
   708         ].
       
   709     chunk := ExternalBytes new:(chunkSize := self primitiveChunkSize).
       
   710     fragmentHeader := '<?xml version="1.0" ?><fragment>' .
       
   711     fragmentFooter := '</fragment>'.
       
   712     self primitiveCreateExpatParser.
       
   713     aStream binary.
       
   714     self expatStartDocumentFragment.
       
   715     [
       
   716         chunk replaceBytesFrom:1 to:fragmentHeader size with:fragmentHeader startingAt:0.
       
   717 
       
   718         (self primitiveParseChunk:fragmentHeader len:fragmentHeader size) ifFalse:[
       
   719                 self getErrorHandler fatalError:(SAXError withMessage:'Hmm...cannot parse').
       
   720                 self primitiveFreeExpatParser. 
       
   721                 ^self
       
   722         ].
       
   723         [aStream atEnd] whileFalse:[
       
   724             aStream readWait.
       
   725             bytesRead := aStream nextBytes:chunkSize into:chunk.
       
   726             (self primitiveParseChunk:chunk len:bytesRead) ifFalse:[
       
   727                 self getErrorHandler fatalError:(SAXError withMessage:'Hmm...cannot parse').
       
   728                 self primitiveFreeExpatParser. 
       
   729                 ^self
       
   730             ]
       
   731         ].
       
   732         chunk replaceBytesFrom:1 to:fragmentFooter size with:fragmentFooter startingAt:0.
       
   733         (self primitiveParseChunk:chunk len:fragmentFooter size) ifFalse:[
       
   734                 self getErrorHandler fatalError:(SAXError withMessage:'Hmm...cannot parse').
       
   735                 self primitiveFreeExpatParser. 
       
   736                 ^self
       
   737         ].
       
   738         self expatEndDocumentFragment.
       
   739     ] ensure:[
       
   740         self primitiveFreeExpatParser.
       
   741         chunk free
       
   742     ].
       
   743 
       
   744     "Created: / 23-04-2005 / 14:16:13 / janfrog"
       
   745     "Modified: / 15-07-2010 / 16:30:50 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   746 
       
   747 !
       
   748 
       
   749 parseStream:aStream
       
   750 
       
   751     | chunk chunkSize bytesRead |
       
   752     aStream isReadable ifFalse:[
       
   753         self getErrorHandler fatalError:
       
   754             (SAXError withMessage:'Stream is not readable')
       
   755         ].
       
   756     chunk := ExternalBytes new:(chunkSize := self primitiveChunkSize).
       
   757     [
       
   758         self primitiveCreateExpatParser.
       
   759         aStream binary.
       
   760         self expatStartDocument.
       
   761         [aStream atEnd] whileFalse:[
       
   762             aStream readWait.
       
   763             bytesRead := aStream nextBytes:chunkSize into:chunk.
       
   764             (self primitiveParseChunk:chunk len:bytesRead) ifFalse:[
       
   765                 self getErrorHandler fatalError:(SAXError withMessage:'Hmm...cannot parse').
       
   766                 self primitiveFreeExpatParser.            
       
   767             ]
       
   768         ].        
       
   769         self expatEndDocument.
       
   770     ] ensure: [
       
   771         self primitiveFreeExpatParser.
       
   772         chunk free
       
   773     ]
       
   774 
       
   775     "Created: / 21-04-2005 / 19:37:05 / janfrog"
       
   776     "Modified: / 15-07-2010 / 09:29:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   777 ! !
       
   778 
       
   779 !ExpatXMLReader class methodsFor:'documentation'!
       
   780 
       
   781 version
       
   782     ^ '$Id$'
       
   783 
       
   784 !
       
   785 
       
   786 version_SVN
       
   787     ^ '$Id$'
       
   788 ! !
       
   789