You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by an...@locus.apache.org on 2000/07/18 20:26:20 UTC

cvs commit: xml-xerces/c/src/util/Transcoders/MacOSUnicodeConverter MacOSUnicodeConverter.cpp MacOSUnicodeConverter.hpp

andyh       00/07/18 11:26:17

  Modified:    c/Projects/MacOS ReadmeForMacOS.txt
               c/doc    faq-other.xml faq-parse.xml
               c/src/util AutoSense.hpp
               c/src/util/Compilers CodeWarriorDefs.hpp
               c/src/util/Platforms/MacOS MacOSPlatformUtils.cpp
  Added:       c/Projects/MacOS ShortenFiles.pl
               c/src/util/Compilers CodeWarriorDefs.cpp
               c/src/util/Platforms/MacOS MacOSPlatformUtils.hpp
               c/src/util/Transcoders/MacOSUnicodeConverter
                        MacOSUnicodeConverter.cpp MacOSUnicodeConverter.hpp
  Log:
  Mac OS update.
  Contributed by James Berry <jb...@criticalpath.com>
  
  Revision  Changes    Path
  1.2       +73 -70    xml-xerces/c/Projects/MacOS/ReadmeForMacOS.txt
  
  Index: ReadmeForMacOS.txt
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/Projects/MacOS/ReadmeForMacOS.txt,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ReadmeForMacOS.txt	1999/11/09 01:10:46	1.1
  +++ ReadmeForMacOS.txt	2000/07/18 18:25:46	1.2
  @@ -1,71 +1,74 @@
  -Disclaimer:
  +State of Xerces Mac OS Port. 7/14/00 by James Berry, Critical Path Software, Inc.
   
  -    XML4C is not officially supported under MacOS. These instructions
  -    were provided by one of the contributers/users of XML4C and have
  -    been included in the XML4C distribution just for convenience and
  -    benefit of other users. XML4C team, will not be able to maintain
  -    these files, but will be very willing to accept changes as
  -    submitted by the users. All such changes may be sent to
  -    xml4c@us.ibm.com.
  -
  -
  -The directions in this file cover installing and building XML4C and
  -ICU under the MacOS using CodeWarrior.
  -
  -1.  Create a folder that will contain the XML4C and ICU distributions.
  -      For future reference I will refer to this folder as "src drop".
  -      
  -2.  Download and uncompress the ICU 1.2.5 source distribution and the
  -      XML4C 2.3.1 source distribution.  You might also want to download
  -      the binary distributions because they may contain documentation
  -      not present in the source distribution.  This will create two additional
  -      folders: "xml4csrc2_3_1" and "icu".  Move these two folders into the
  -      "src drop" folder.
  -      
  -3.  Drag the xml4csrc2_3_1 folder and drop it on to the "rename files" application
  -      located in the same folder as this readme.  This is a MacPerl
  -      script that renames files with names too long to fit in the HFS/HFS+
  -      filesystem.  It also searches through all of the source code and
  -      changes the #include statements to refer to the new file names.
  -      
  -4.  Move all the files from the "XML4C MacOS Drop:icu changes:common:" folder
  -      to the "src drop:icu:source:common:" folder, replacing the existing files
  -      in the icu source drop.
  -      
  -5.  Move the file from the "XML4C MacOS Drop:icu changes:extra:ustdio:" folder
  -      to the "src drop:icu:source:extra:ustdio:" folder, replacing the existing file
  -      in the icu source drop.
  -      
  -6.  Move the MacOS folder (in the Projects folder) to "src drop:xml4csrc2_3_1:Projects".
  -
  -7.  You should be able to open the CodeWarrior project file
  -       "src drop:xml4c2:Projects:MacOS:xml4c:xml4c" and build the xml4c library.
  -       
  -8.  You should also be able to open the CodeWarrior project file
  -       "src drop:xml4c2_3_1:Projects:MacOS:icu:icu" and build the ICU library.
  -       
  -9.  If you wish you can create projects for and build the rest of
  -       the tools and test suites.  They are not needed if you just want to
  -       use xml4c.  I suggest that you use the binary data files distributed
  -       with the binary distribution of ICU instead of creating your own from
  -       the text data files in the ICE source distribution.
  -       
  -There are some things to be aware of when creating your own projects using
  -xml4c.
  -
  -1.  You will need to link against both the ICU and XML4C libraries.
  -
  -2.  The options "Always search user paths" and "Interpret DOS and Unix Paths"
  -       are very useful.  Some of the code won't compile without them set.
  -       
  -3.  Most of the tools and test code will require slight modification to compile
  -       and run correctly (typecasts, command line parameters, etc), but it is
  -       possible to get them working correctly.
  -       
  -4.  You will most likely have to set up the Access Paths.  The access paths in the
  -       xml4c projects should serve as a good example.
  -       
  -If you are having problems getting xml4c working feel free to email
  -me at jbellardo@alumni.calpoly.edu.  I may or may not be able to help
  -(depending on things out of my control like work/class schedules) but I will
  -try.
  +This readme attempts to document the state of Mac OS support for Xerces.
  +I suspect that this code has been ported to the Mac on a number of occasions.
  +My work on Xerces is derived in small part from a previous port by jbellardo@calpoly.edu.
  +
  +This port aims to bring Xerces to Mac OS, and to use Mac OS services as appropriate.
  +
  +Key work in these areas is:
  +
  + - Development of a transcoder that relies on Mac OS's Unicode Converter. [MacOSUnicodeConverter].
  +
  + - Near-complete rewrite of Mac OS Platform utilities [MacOSPlatformUtils] to support Mac OS
  +   constructs and the latest changes in Xerces. All file access is done directly on top of the
  +   Mac OS file system and in fact uses the new FSRef calls and long unicode names
  +   whereever possible.
  +
  + - Code supports both Carbon and Classic APIs.
  +
  + - Detection of and support for Codewarrior and Project Builder.
  +
  +Key omissions include:
  +
  + - Neither Codewarrior nor Project Builder project files are yet provided, though I've built
  +   both. My Codewarrior projects are built under the new IDE 4.1 which has not yet been
  +   publicly released. I'll release Project Builder projects after the Mac OS X public beta
  +   is released. If you want them now...just email me.
  +
  + - There is no NetAccessor support yet for Mac OS. This could/should probably be written
  +   atop URL Access, and probably isn't that hard, but I haven't gotten around to it yet.
  +   Other possibilities might include using libwww or the existing Xerces NetSocket accessor
  +   if you're under Mac OS X.
  +
  +Usage Notes:
  +
  + - A major hassle in porting this code to the Mac, and in keeping it up to date, is the
  +   existance of a number of files with file names greater than 31 characters. Xalan is worse.
  +   I've written a perl script "ShortenNames.pl" which will (1) copy source to a MacSrc directory
  +   (2) shorten file names using appropriate hints, and (3) update internal usage of these
  +   names (includes). To use this:
  +
  +   - Check out the code somewhere where you've got long names [unix system?]
  +   - Move ShortenNames.pl into the "c" directory, at the same level as the
  +     "src" directory.
  +   - Invoke the script using perl ShortenNames.pl.
  +   - This (should) create a new directory called MacSrc which is a duplicate of
  +     the "src" directory but with names shortened appropriately. This has been
  +     tested on Mac OS and Mac OS X, but in no other environments. YMMV.
  +
  +   Note that I'll ascribe most of the blame for the problem to Apple and other Mac tools
  +   vendors. HFS+ fully supports long file names: it's too bad that Apple (Finder),
  +   Aladdin (StuffIt), Metrowerks (CodeWarrior) and others (MacCVS) haven't chosen to support
  +   long names within their products. I actually spent several days on the MacCVS end of this
  +   task before deciding it was too hard given the timeframe with OS X almost here.
  +   The situation under Mac OS X is much better.
  +
  + - The Mac OS Platform utilities expect that pathnames will be in unix-form with '/' separators.
  +   There is no support for Mac OS style pathnames with colons. Routines are provided to
  +   convert back and forth between this style of name and FSRefs or FSSpecs. See
  +   [MacOSPlatformUtils.hpp]. The choice to use unix-paths only was based on the idea that
  +   any XML that has external references is likely to have them in unix form, so we have to
  +   be able to support unix paths. To also support mac paths seems superfluous.
  +
  + - I have not brought forward the previous port's rather bizzare support for file sources
  +   that read from resources. If you want to read from a resource just read it into memory,
  +   lock it down, and set up a memory based stream to parse through it.
  +
  + - If you're building this code, make sure you include the MemoryBased messaged loader.
  +   There is no Mac specific message loader for now.
  +
  +
  +James Berry
  +Critical Path Software, Inc.
  +jberry@criticalpath.com
  \ No newline at end of file
  
  
  
  1.1                  xml-xerces/c/Projects/MacOS/ShortenFiles.pl
  
  Index: ShortenFiles.pl
  ===================================================================
  use Config;
  use FindBin;
  use File::Find;
  use File::Path;
  
  #	Constants
  $kMaxLength = 31;
  
  # Globals
  $gScriptBase = $FindBin::RealBin;
  $gPathSep = GetPathSeparator();
  
  $gSrcBase = $gScriptBase.$gPathSep."src";
  $gDstBase = $gScriptBase.$gPathSep."MacSrc";
  
  # Map from unshortened to shortened name
  %gBadMap;
  
  # Hints for shortening names
  @gHints =
  (
  	["Exception",		"Except"	],
  	["Implementation",	"Impl"		],
  	["Reference",		"Ref"		],
  	["Documentation",	"Doc"		],
  	["Document",		"Doc"		],
  	["Definition",		"Def"		],
  	["Count",			"Cnt"		],
  	["Entity",			"Ent"		],
  	["Character",		"Char"		],
  	["Processing",		"Proc"		],
  	["Instruction",		"Instr"		],
  	["Parent",			"Par"		],
  	["Fragment",		"Frag"		],
  );
  
  sub GetPathSeparator
  {
  	if ($^O eq 'MSWin32')
  	{
  		return '\\';
  	}
  	elsif ($^O eq 'MacOS')
  	{
  		return ':';
  	}
  	else
  	{
  		return '/';
  	}
  }
  
  
  sub ShortenName
  {
  	$newName = $_;
  	
  LOOP:
  	while (length($newName) > $kMaxLength)
  	{
  		foreach $hint (@gHints)
  		{
  			$pattern		= $hint->[0];
  			$replacement	= $hint->[1];
  			if ($newName =~ s/$pattern/$replacement/)
  			{
  				#print "\tmatched ".$hint->[0]."; replaced with ".$hint->[1]."\n";
  				next LOOP;
  			}
  		}
  		
  		# No hint found, so we need to shorten the name manually
  		$kill = length($newName) - $kMaxLength + 1;
  		substr($newName, $kMaxLength / 2, $kill) = "�";
  		#print "\tshorten manually\n";
  	}
  	
  	return $newName;
  }
  
  
  sub Gather
  {
  	$path = $File::Find::name;
  	$name = $_;
  	
  	if (-f $path)
  	{
  		if (length($name) > $kMaxLength)
  		{
  			#print "$name is too long\n";
  			$newName = ShortenName($name);
  			#print "--> ".$newName."\n";
  			
  			# Add an entry to our bad map
  			$gBadMap{$name} = $newName
  		}
  	}
  	else
  	{
  		#print "NOT A FILE: $File::Find::dir".$_."\n";
  	}
  }
  
  
  sub GatherBadFiles
  {
  	find(\&Gather, $gSrcBase);
  }
  
  
  sub Copy
  {
  	# Caller wants $_ the same across this call
  	$save_ = $_;
  	
  	$_ = "" if ($_ eq '.');
  	 
  	# remap the destination name as needed
  	$srcName = $_;
  	$dstName = $srcName;
  	if (exists $gBadMap{$srcName})
  	{
  		$dstName = $gBadMap{$srcName};
  		print "Renaming file $srcName --> $dstName\n";
  	}
  		
  	$srcPath = $File::Find::name;
  	$dstPath = $srcPath;
  		
  	# Interpolate paths
  	$dstPath =~ s/$srcName$/$dstName/;
  	$dstPath =~ s/^$gSrcBase/$gDstBase/;
  	
  #print "srcName $srcName, dstName $dstName, srcPath $srcPath, dstPath $dstPath\n";
  	
  	if (-d $srcPath && not -e $dstPath)
  	{
  		# make the dst directory
  		print "Making directory $dstPath\n";
  		mkpath($dstPath);
  	}
  	else
  	{
  		# Copy the file, fixing up includes as we go
  		
  		# Open files
  		open(SRC, "< $srcPath")         or die "can't open $srcPath: $!";
  		open(DST, "> $dstPath")         or die "can't open $dstPath: $!";
  		
  		# Copy the file a line at a time
  		while (<SRC>)
  		{
  			# Look for an include line
  			if (	/^(\s*)#(\s*)include(\s*)<(\s*)(.*)(\s*)>(.*)/
  				 || /^(\s*)#(\s*)include(\s*)"(\s*)(.*)(\s*)"(.*)/
  			   )
  			{
  				# We've got the include file name (path).
  				# Now isolate just the leaf of that
  				$includePath = $5;
  				
  				$includePath =~ /^([^\/]*\/)*([^\/]+)$/;
  				$includeLeaf = $2;
  				
  				# Check for the include file in our bad map, replacing
  				# it as necessary
  				if (exists $gBadMap{$includeLeaf})
  				{
  					$dup = $_;
  					$was = $includeLeaf;
  					$sub = $gBadMap{$was};
  					
  					s/^(.*)include(.*)$was(.*)/$1include$2$sub$3/;
  					print "file $srcName: changed include $includePath --> $_";
  					#print "Change $dup to $_";
  				}
  			}
  			
  			# Output the modified (or not) line
  			(print DST $_)				or die "can't write to $dstPath: $!";
  		}
  		
  		# Close 'dem files
  		close(SRC)                 		or die "can't close $srcPath: $!";
  		close(DST)                  	or die "can't close $dstPath: $!";
  	}
  	
  	$_ = $save_;
  }
  
  
  sub CopyFiles
  {
  	find(\&Copy, $gSrcBase);
  }
  
  
  # Tell what we know:
  print "\n";
  print "Script:                $0\n";
  print "Source Directory:      $gSrcBase\n";
  print "Destination Directory: $gDstBase\n";
  print "\n";
  
  #-- Scan phase
  #for each .cpp or .hpp or .c or .cc file in tree
  #	if name too long
  #		shorten the name
  # store it in a map
  # end if
  #end for
  
  # Gather up the bad files into global map gBadMap
  print "Scanning...\n";
  undef %gBadMap;
  GatherBadFiles($srcBase);
  
  # Print bad map
  #print "BadMap:\n";
  #foreach $key (sort(keys %gBadMap)) {
  #	print $key, '=', $gBadMap{$key}, "\n";
  #}
  
  #-- Copy/Modify phase
  #for each file in tree
  # copy file to new directory, scanning for include as we go
  # if include contains a name from the map
  # then replace it
  #end for
  print "Copying...\n";
  CopyFiles($srcBase, $dstBase);
  
  print "\nDone\n";
  
  
  
  
  1.6       +53 -0     xml-xerces/c/doc/faq-other.xml
  
  Index: faq-other.xml
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/doc/faq-other.xml,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- faq-other.xml	2000/06/01 01:31:14	1.5
  +++ faq-other.xml	2000/07/18 18:25:51	1.6
  @@ -15,6 +15,17 @@
       </faq>
   
   
  +
  +    <faq title="What are the differences between Xerces-C and IBM XML4C?">
  +        <q>"What are the differences between Xerces-C and IBM XML4C?"</q>
  +        <a>
  +            <p>XML4C from IBM is based on the Xerces-C code.  The
  +               only difference is that XML4C is bundled together
  +               with IBM's ICU classes for Unicode support, which
  +               allow it to support a wider range of character
  +               set encodings.</p>
  +        </a>
  +    </faq>
       <faq title="Is there any kind of support available for Xerces-C/XML4C?">
           <q>Is there any kind of support available for Xerces-C/XML4C?</q>
           <a>
  @@ -39,6 +50,17 @@
           </a>
       </faq>
   
  +    <faq title="Where can I find additional information on XML?">
  +    <q>Where can I find additional information on XML?</q>
  +    <a>
  +        <p>The Web.  <jump href="http://www.oasis-open.org/cover/xml.html">
  +        http://www.oasis-open.org/cover/xml.html</jump> is an excellent
  +        place to start, with links to overviews, FAQs, specifications,
  +        industry news, applications and other software, related standards,
  +        etc.</p>
  +    </a>
  +    </faq>
  +
       <faq title="I found a defect - how do I report it?">
           <q>I found a defect - how do I report it?</q>
           <a>
  @@ -80,6 +102,37 @@
                  change is.  (Working with the current sources is important)</p>
   
           </a>
  +    </faq>
  +
  +
  +    <faq title="How do I port Xerces-C to a new platform?">
  +    <q>How do I port Xerces-C to a new platform?</q>
  +    <a>
  +        <p>(from Dean Roddey) The primary work of a port involved creating:</p>
  +
  +        <ol>
  +        <li>A new compiler header for the compiler</li>
  +        <li>A new platform utilities file that implements the little bit of system
  +        access we need, and an associated header.</li>
  +        <li>Updating XercesDefs.hpp and AutoSense.hpp to get your new headers
  +        included when compiled under your OS and compiler.</li>
  +        </ol>
  +
  +        <p>Other concerns are:</p>
  +
  +        <ol>
  +        <li>Does ICU compile on your platform? If not, then you'll need to do a
  +        transcoder implementation that uses your local transcoding services. I
  +        assume that the Iconv transcoder would work for you, though perhaps with
  +        some modifications.</li>
  +
  +        <li>What message loader will you use. For starting off, you can use the 'in
  +        memory' one which is very simple and easy. Then, once you get going, you'll
  +        want to possibly adapt the message catalog message loader or write one of
  +        your own that uses local services of some sort.</li>
  +        </ol>
  +
  +    </a>
       </faq>
   
   </faqs>
  
  
  
  1.16      +36 -1     xml-xerces/c/doc/faq-parse.xml
  
  Index: faq-parse.xml
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/doc/faq-parse.xml,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- faq-parse.xml	2000/06/20 22:51:09	1.15
  +++ faq-parse.xml	2000/07/18 18:25:52	1.16
  @@ -162,9 +162,27 @@
     </faq>
   
   
  +<faq title="I am seeing memory leaks for Xerces-C.  Are they real?">
  +<q>I am seeing memory leaks for Xerces-C.  Are they real?</q>
  +        <a>
  +        <p>The Xerces library allocates and caches some commonly reused
  +        items.  The storage for these may be reported as memory leaks by some heap analysis
  +        tools; to avoid the problem, call the function
  +        <code>XMLPlatformUtils::Terminate()</code> before your application exits.
  +        This will free all memory that was being held by the library.</p>
  +
  +        <p>For most applications, the use of <code>Terminate()</code> is optional.
  +        The system will recover all memory when the application process shuts down.
  +        The exception to this is the use of Xerces-C from DLLs that will be
  +        repeatedly loaded and unloaded from within the same process.  To avoid
  +        memory leaks with this kind of use, <code>Terminate()</code> must be called before
  +        unloading the xerces-c library</p>
  +        </a>
  +</faq>
  +
   <faq title="Can I validate the data contained in a DOM tree?">
        <q>Can I validate the data contained in a DOM tree?</q>
  -     <a><p>Given that I have built a DOM tree, is there a fiacility
  +     <a><p>Given that I have built a DOM tree, is there a facility
        in xerces-c that wil then validate the document contained in that
        DOM tree?  That is, without having to re-parse the source document,
        walk the tree and perform validation?</p>
  @@ -176,6 +194,23 @@
        </a>
   </faq>
   
  +<faq title="Can I use Xerces to perform write validation">
  +    <q>
  +        Can I use Xerces to perform "write validation" (which is having an
  +        appropriate DTD and being able to add elements to the DOM whilst validating
  +        against the DTD)?  Is there a function that I have totally
  +        misssed that creates an XML file from a DTD,
  +        (obviously with the values missing, a skeleton, as it were.)
  +    </q>
  +
  +    <a>
  +        <p>The answers are No and No.  Write Validation is a commonly requested
  +        feature, but xerces doesn't have it yet.</p>
  +
  +        <p>The best you can do for now is to create the DOM document, write it
  +        back as XML and re-parse it. </p>
  +    </a>
  +</faq>
   
       <faq title="Why does my multi-threaded application crash on Solaris?">
           <q>Why does my multi-threaded application crash on Solaris?</q>
  
  
  
  1.13      +5 -0      xml-xerces/c/src/util/AutoSense.hpp
  
  Index: AutoSense.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/util/AutoSense.hpp,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- AutoSense.hpp	2000/04/04 20:11:29	1.12
  +++ AutoSense.hpp	2000/07/18 18:25:58	1.13
  @@ -56,6 +56,10 @@
   
   /*
    * $Log: AutoSense.hpp,v $
  + * Revision 1.13  2000/07/18 18:25:58  andyh
  + * Mac OS update.
  + * Contributed by James Berry <jb...@criticalpath.com>
  + *
    * Revision 1.12  2000/04/04 20:11:29  abagchi
    * Added PTX support
    *
  @@ -165,6 +169,8 @@
   
   #elif defined(macintosh)
       #define XML_MACOS
  +#elif defined(MACOSX)
  +    #define XML_MACOSX
   #else
       #error Code requires port to host OS!
   #endif
  
  
  
  1.6       +37 -17    xml-xerces/c/src/util/Compilers/CodeWarriorDefs.hpp
  
  Index: CodeWarriorDefs.hpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/util/Compilers/CodeWarriorDefs.hpp,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- CodeWarriorDefs.hpp	2000/03/02 19:55:07	1.5
  +++ CodeWarriorDefs.hpp	2000/07/18 18:26:04	1.6
  @@ -1,37 +1,37 @@
   /*
    * The Apache Software License, Version 1.1
  - * 
  + *
    * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
    * reserved.
  - * 
  + *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
  - * 
  + *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  - * 
  + *    notice, this list of conditions and the following disclaimer.
  + *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
    *    the documentation and/or other materials provided with the
    *    distribution.
  - * 
  + *
    * 3. The end-user documentation included with the redistribution,
  - *    if any, must include the following acknowledgment:  
  + *    if any, must include the following acknowledgment:
    *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowledgment may appear in the software itself,
    *    if and wherever such third-party acknowledgments normally appear.
  - * 
  + *
    * 4. The names "Xerces" and "Apache Software Foundation" must
    *    not be used to endorse or promote products derived from this
  - *    software without prior written permission. For written 
  + *    software without prior written permission. For written
    *    permission, please contact apache\@apache.org.
  - * 
  + *
    * 5. Products derived from this software may not be called "Apache",
    *    nor may "Apache" appear in their name, without prior written
    *    permission of the Apache Software Foundation.
  - * 
  + *
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  @@ -45,7 +45,7 @@
    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    * SUCH DAMAGE.
    * ====================================================================
  - * 
  + *
    * This software consists of voluntary contributions made by many
    * individuals on behalf of the Apache Software Foundation, and was
    * originally based on software copyright (c) 1999, International
  @@ -56,6 +56,10 @@
   
   /*
    * $Log: CodeWarriorDefs.hpp,v $
  + * Revision 1.6  2000/07/18 18:26:04  andyh
  + * Mac OS update.
  + * Contributed by James Berry <jb...@criticalpath.com>
  + *
    * Revision 1.5  2000/03/02 19:55:07  roddey
    * This checkin includes many changes done while waiting for the
    * 1.1.0 code to be finished. I can't list them all here, but a list is
  @@ -103,19 +107,34 @@
   // #define NO_NATIVE_BOOL
   
   
  +// ---------------------------------------------------------------------------
  +//  Define our version of the XMLCh. XMLCh should be mapped to the native
  +//  wide char type (whatever wchar_t is.) On Mac, wchar_t is not an
  +//  intrinsic type and is just mapped to unsigned short.
  +// ---------------------------------------------------------------------------
  +typedef unsigned short  XMLCh;
  +typedef unsigned short  UTF16Ch;
  +
  +
   // ---------------------------------------------------------------------------
  -//  Define our version of the XMLCh.
  +//  Define unsigned 16 and 32 bits integers
   // ---------------------------------------------------------------------------
  -typedef unsigned short XMLCh;
  +typedef unsigned short  XMLUInt16;
  +typedef unsigned int    XMLUInt32;
   
   
   // ---------------------------------------------------------------------------
   //  Force on the Xerces debug token if it was on in the build environment
   // ---------------------------------------------------------------------------
  -//#ifdef _DEBUG
  -//#define XERCES_DEBUG
  -//#endif
  +#ifdef _DEBUG
  +#define XERCES_DEBUG
  +#endif
   
  +// ---------------------------------------------------------------------------
  +//  Provide some common string ops that are different/notavail for CodeWarrior.
  +// ---------------------------------------------------------------------------
  +int stricmp(const char* const str1, const char* const  str2);
  +int strnicmp(const char* const str1, const char* const  str2, const unsigned int count);
   
   // ---------------------------------------------------------------------------
   //  The name of the DLL that is built by the Codewarrior version of the
  
  
  
  1.1                  xml-xerces/c/src/util/Compilers/CodeWarriorDefs.cpp
  
  Index: CodeWarriorDefs.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   * 
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   * 
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   * 
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   * 
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache\@apache.org.
   * 
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   * 
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   * 
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  #include <utils/Compilers/CodeWarriorDefs.hpp>
  
  #include <ctype.h>
  
  // These functions are needed because MacOS doesn't define them
  // even though they are used.
  // Compare lexigraphically two strings
  int stricmp(const char *s1, const char *s2)
  {
      char c1, c2;
      while (1)
      {
          c1 = tolower(*s1++);
          c2 = tolower(*s2++);
          if (c1 < c2) return -1;
          if (c1 > c2) return 1;
          if (c1 == 0) return 0;
      }
  }
  
  // Compare lexigraphically two strings up to a max length
  int strnicmp(const char *s1, const char *s2, int n)
  {
      int i;
      char c1, c2;
      for (i=0; i<n; i++)
      {
          c1 = tolower(*s1++);
          c2 = tolower(*s2++);
          if (c1 < c2) return -1;
          if (c1 > c2) return 1;
          if (!c1) return 0;
      }
      return 0;
  }
  
  
  
  
  
  
  
  1.5       +1122 -550 xml-xerces/c/src/util/Platforms/MacOS/MacOSPlatformUtils.cpp
  
  Index: MacOSPlatformUtils.cpp
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/util/Platforms/MacOS/MacOSPlatformUtils.cpp,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- MacOSPlatformUtils.cpp	2000/03/02 21:10:37	1.4
  +++ MacOSPlatformUtils.cpp	2000/07/18 18:26:09	1.5
  @@ -1,37 +1,37 @@
   /*
    * The Apache Software License, Version 1.1
  - * 
  + *
    * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
    * reserved.
  - * 
  + *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
  - * 
  + *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  - * 
  + *    notice, this list of conditions and the following disclaimer.
  + *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
    *    the documentation and/or other materials provided with the
    *    distribution.
  - * 
  + *
    * 3. The end-user documentation included with the redistribution,
  - *    if any, must include the following acknowledgment:  
  + *    if any, must include the following acknowledgment:
    *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowledgment may appear in the software itself,
    *    if and wherever such third-party acknowledgments normally appear.
  - * 
  + *
    * 4. The names "Xerces" and "Apache Software Foundation" must
    *    not be used to endorse or promote products derived from this
  - *    software without prior written permission. For written 
  + *    software without prior written permission. For written
    *    permission, please contact apache\@apache.org.
  - * 
  + *
    * 5. Products derived from this software may not be called "Apache",
    *    nor may "Apache" appear in their name, without prior written
    *    permission of the Apache Software Foundation.
  - * 
  + *
    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  @@ -45,7 +45,7 @@
    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    * SUCH DAMAGE.
    * ====================================================================
  - * 
  + *
    * This software consists of voluntary contributions made by many
    * individuals on behalf of the Apache Software Foundation, and was
    * originally based on software copyright (c) 1999, International
  @@ -56,6 +56,10 @@
   
   /*
    * $Log: MacOSPlatformUtils.cpp,v $
  + * Revision 1.5  2000/07/18 18:26:09  andyh
  + * Mac OS update.
  + * Contributed by James Berry <jb...@criticalpath.com>
  + *
    * Revision 1.4  2000/03/02 21:10:37  abagchi
    * Added empty function platformTerm()
    *
  @@ -91,319 +95,275 @@
   #include <util/Janitor.hpp>
   #include <util/PlatformUtils.hpp>
   #include <util/RuntimeException.hpp>
  -#include <util/String.hpp>
   #include <util/XMLUni.hpp>
  -#include <util/MacOSDefs.hpp>
  -#include <iostream.h>
  -#include <files.h>
  -#include <gestalt.h>
  -#include <traps.h>
  -#include <lowmem.h>
  -#include <Multiprocessing.h>
  +#include <util/XMLString.hpp>
  +#include <util/Platforms/MacOS/MacOSDefs.hpp>
  +#include <util/Platforms/MacOS/MacOSPlatformUtils.hpp>
  +#include <util/MsgLoaders/InMemory/InMemMsgLoader.hpp>
  +#include <util/Transcoders/MacOSUnicodeConverter/MacOSUnicodeConverter.hpp>
  +
   #include <string.h>
   #include <stdlib.h>
  +#include <stdio.h>
  +#include <ctype.h>
  +#include <memory>
  +
  +#include <Files.h>
  +#include <Gestalt.h>
  +#include <Traps.h>
  +#include <TextUtils.h>
  +#include <Multiprocessing.h>
  +#include <DriverSynchronization.h>
   
   
  +//----------------------------------------------------------------------------
  +// Function Prototypes
  +//----------------------------------------------------------------------------
  +#if !TARGET_API_MAC_CARBON
  +static bool  TrapAvailable(UInt16 trapWord);
  +#endif
   
   //----------------------------------------------------------------------------
   //  Local Data
   //
  -//  gFileSystemReady
  -//    This flag indicates if the file system is ready to be used.  The only
  -//    thing that might stop us is the absence of FSspec file manipulation
  -//    routines in the OS.
  -//
   //  gGestaltAvail
   //    This flag indicates the presence of the gestalt manager.  This version
   //    of the MacOS port can not run without it.
  +//
  +//  gFileSystemCompatible
  +//    This flag indicates whether the file system APIs meet our minimum
  +//   requirements.
  +//
  +// gHasFSSpecAPIs
  +//   True if the FSSpecAPIs are available. These are required.
  +//
  +// gHasF2TBAPIs
  +//   True if the FS supports 2 terrabyte calls. These are required for
  +//   use under Carbon.
  +//
  +// gHasHFSPlusAPIs
  +//   True if the FS supports HFSPlus APIs. If this is true, then the
  +//   new Fork calls are used, and all file name and path handling
  +//   uses long unicode names. Note that once a file is opened with
  +//   the fork calls, only fork calls may be used to access it.
   //----------------------------------------------------------------------------
  -static const char *resBaseStr = "/Access The Resource Fork Instead of the data fork?";
  -static bool gFileSystemReady = false;
  -static bool gGestaltAvail = false;
  -static MPCriticalRegionID gCriticalRegion;
  +static bool gGestaltAvail   = false;
  +static bool gFileSystemCompatible = false;
  +static bool gHasFSSpecAPIs   = false;
  +static bool gHasFS2TBAPIs   = false;
  +static bool gHasHFSPlusAPIs   = false;
   
   
   //----------------------------------------------------------------------------
  -// XMLResFile methods
  +// XMLMacFile methods
   //----------------------------------------------------------------------------
  -XMLResFile::XMLResFile();
  -        
   
  -void XMLResFile::open(const char* const resInfo)
  +unsigned int XMLMacFile::currPos()
   {
  -    char option[32], value[32], command[70];
  -    int cmdEnd = 0, cmdStart = 0;
  -    int optEnd = 0, sep;
  -    int mode = -1;
  -    int typeValid = 0;
  +    OSErr err = noErr;
  +    unsigned int pos = 0;
       
  -    if (!strchr(&resInfo[cmdStart], '/'))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Malformed resource locater");
  -        
  -    while(resInfo[cmdEnd] != '/')
  +    if (!mFileValid)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos);
  +    
  +    if (gHasHFSPlusAPIs)
       {
  -        if (strchr(&resInfo[cmdStart], '&') < strchr(&resInfo[cmdStart], '/') && strchr(&resInfo[cmdStart], '&') != 0)
  -            cmdEnd = strchr(&resInfo[cmdStart], '&') - resInfo - 1;
  -        else
  -            cmdEnd = strchr(&resInfo[cmdStart], '/') - resInfo - 1;
  -            
  -        if (cmdEnd - cmdStart > 68)
  -            throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- resource option too long (>68 chars)");
  -            
  -        memcpy(command, &resInfo[cmdStart], cmdEnd - cmdStart + 1);
  -        command[cmdEnd - cmdStart + 1] = 0;
  -        if (!strchr(command, '='))
  -            throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Malformed resource locater");
  -            
  -        sep = strchr(command, '=') - command;
  -        memcpy(option, command, sep);
  -        option[sep] = 0;
  -        memcpy(value, &command[sep+1], strlen(command) - sep);
  -        
  -        if (!strcmp(option, "mode"))
  -        {
  -            if (!strcmp(value, "by_id"))
  -                mode = 1;
  -            else if (!strcmp(value, "by_id1"))
  -                mode = 2;
  -            else if (!strcmp(value, "by_name"))
  -                mode = 3;
  -            else if (!strcmp(value, "by_name1"))
  -                mode = 4;
  -            else
  -                throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- 'mode' has to be 'by_id' or 'by_id1' or 'by_name' or 'by_name1'");
  -        }
  -        if (!strcmp(option, "type"))
  -        {
  -            if (strlen(value) != 4)
  -                throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- 'type' has to be four characters long");
  -            typeValid = 1;
  -            type = 0;
  -            type += value[0] << 24;
  -            type += value[1] << 16;
  -            type += value[2] << 8;
  -            type += value[3];
  -        }
  -        
  -        cmdStart = cmdEnd + 2;
  -        cmdEnd++;
  +        SInt64 bigPos = 0;
  +        err = FSGetForkPosition(mFileRefNum, &bigPos);
  +        if (err == noErr)
  +            pos = bigPos;
       }
  -    
  -    if (mode == 0)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Malformed resource locater requires a 'mode'");
  -    if (typeValid == 0)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Malformed resource locater requires a 'type'");
  -        
  -    switch(mode)
  +    else
       {
  -        case 1: case 2:
  -            id = atol(&resInfo[cmdEnd+1]);
  -            if (mode == 1)
  -                data = GetResource(type, id);
  -            else
  -                data = Get1Resource(type, id);
  -            break;
  -            
  -        case 3: case 4:
  -            if (strlen(&resInfo[cmdEnd]) >= 255)
  -                throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Resource names have to be 255 characters or less");
  -            strcpy((char*)name, &resInfo[cmdEnd]);
  -            name[0] = strlen((char*)&name[1]);
  -            if (mode == 3)
  -                data = GetNamedResource(type, name);
  -            else
  -                data = Get1NamedResource(type, name);
  -            break;
  +        long longPos;
  +        err = GetFPos(mFileRefNum, &longPos);
  +        if (err == noErr)
  +            pos = longPos;
       }
       
  -    if (ResError() != noErr)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Error opening resource");
  -        
  -    GetResInfo(data, &id, &type, name);
  -    len = GetResourceSizeOnDisk(data);
  -    if (ResError() != noErr)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Error loading resource info");
  -        
  -    valid = 1;
  -}
  -
  -unsigned int XMLResFile::read(const unsigned int buffLen, XMLByte* const buff)
  -{
  -    unsigned int totAvail = len - pos;
  -    unsigned int numRead = (buffLen >= totAvail) ? totAvail : buffLen;
  +    if (err != noErr)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetCurPos);
       
  -    HLock(data);
  -    memcpy(buff, *data, numRead);
  -    HUnlock(data);
  -    pos += numRead;
  -    return numRead;
  -}
  -
  -void XMLResFile::close()
  -{
  -    if (!valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::curFilePos -- Not a valid file");
  -    ReleaseResource(data);
  -    valid = 0;
  -}
  -        
  -unsigned int XMLResFile::currPos()
  -{
  -    if (!valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::curFilePos -- Not a valid file");
       return pos;
   }
   
  -void XMLResFile::reset()
  -{
  -    if (!valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::resetFile -- Not a valid file");
  -    pos = 0;
  -}
  -
  -unsigned int XMLResFile::size()
  -{
  -    if (!valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::fileSize -- Not a valid file");
  -    return len;
  -}
   
  -XMLResFile::~XMLResFile()
  +void XMLMacFile::close()
   {
  -    if (valid)
  -        close();
  +    OSErr err = noErr;
  +    if (!mFileValid)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
  +    
  +    if (gHasHFSPlusAPIs)
  +        err = FSCloseFork(mFileRefNum);
  +    else
  +        err = FSClose(mFileRefNum);
  +    
  +    mFileValid = false;
  +    
  +    if (err != noErr)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotCloseFile);
   }
   
  -//----------------------------------------------------------------------------
  -// XMLMacFile methods
  -//----------------------------------------------------------------------------
   
  -unsigned int XMLMacFile::currPos()
  +unsigned int
  +XMLMacFile::size()
   {
  -    long len;
  -    if (!valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::curFilePos -- Not a valid file");
  -    if (noErr != GetFPos(fileRef, &len))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::curFilePos -- Error getting file position");
  +    OSErr err = noErr;
  +    unsigned int len = 0;
  +    
  +    if (!mFileValid)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetSize);
  +    
  +    if (gHasHFSPlusAPIs)
  +    {
  +        SInt64 bigLen = 0;
  +        err = FSGetForkSize(mFileRefNum, &bigLen);
  +        if (err == noErr)
  +            len = bigLen;
  +    }
  +    else
  +    {
  +        long longLen;
  +        err = GetEOF(mFileRefNum, &longLen);
  +        if (err == noErr)
  +            len = longLen;
  +    }
  +    
  +    if (err != noErr)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotGetSize);
  +    
       return len;
   }
   
  -void XMLMacFile::close()
  -{
  -    if (!valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::closeFile -- Not a valid file");
  -    if (noErr != FSClose(fileRef))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::closeFile -- Error closing file");
  -    valid = 0;
  -}
   
  -unsigned int XMLMacFile::size()
  +void XMLMacFile::open(const XMLCh* const fileName)
   {
  -    long len;
  +    OSErr err = noErr;
       
  -    if (!valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::fileSize -- Not a valid file");
  -    if (noErr != GetEOF(fileRef, &len))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::fileSize -- Error closing file");
  -    return len;
  -}
  -
  -void XMLMacFile::open(const char* const fileName)
  -{
  -    OSErr myErr;
  -
  -    if (valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Can't open the same file twice");
  -    if (strlen(fileName) > 255)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile(const char* const) -- File name too long (>255 chars)");
  -        
  -    if (fileName[0] == '/')
  -    {
  -        strcpy((char*)&pStr[1], &fileName[1]);
  -        pStr[0] = strlen(fileName) - 1;
  -        pStr[strlen(fileName)] = 0;
  -    } else {
  -        strcpy((char*)&pStr[1], fileName);
  -        pStr[0] = strlen(fileName);
  -        pStr[strlen(fileName) + 1] = 0;
  -    }
  +    if (mFileValid)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotOpenFile);
       
  -    for(int i = 1; i <= pStr[0]; i++)
  -        if (pStr[i] == '/')
  -            pStr[i] = ':';
  -            
  -    myErr = HOpenDF(0, 0, pStr, fsRdWrPerm, &fileRef);
  -    if (myErr != noErr)
  +    if (gHasHFSPlusAPIs)
       {
  -        cerr << myErr << endl;
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile(const char* const) -- Failed to open file.");
  +        FSRef ref;
  +        if (!XMLParsePathToFSRef(fileName, ref))
  +            err = fnfErr;
  +        
  +        HFSUniStr255 forkName;
  +        if (err == noErr)
  +            err = FSGetDataForkName(&forkName);
  +        
  +        if (err == noErr)
  +            err = FSOpenFork(&ref, forkName.length, forkName.unicode, fsRdWrPerm, &mFileRefNum);
       }
  +    else
  +    {
  +        FSSpec spec;
  +        if (!XMLParsePathToFSSpec(fileName, spec))
  +            err = fnfErr;
           
  -    valid = 1;
  +        if (err == noErr)
  +            err = FSpOpenDF(&spec, fsRdWrPerm, &mFileRefNum);
  +    }
  +    
  +    if (err != noErr)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotOpenFile);
  +    
  +    mFileValid = true;
   }
   
   unsigned int XMLMacFile::read(const unsigned int toRead, XMLByte* const toFill)
   {
  -    long bytesRead = toRead;
  -
  -    if (!valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::readFileBuff -- Not a valid file");
  -    if (noErr != FSRead(fileRef, &bytesRead, toFill))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::readFileBuffer - Read failed");
  -    return (unsigned int)bytesRead;
  +    unsigned int bytesRead = 0;
  +    OSErr err = noErr;
  +    
  +    if (!mFileValid)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile);
  +    
  +    if (gHasHFSPlusAPIs)
  +    {
  +        ByteCount actualCount;
  +        err = FSReadFork(mFileRefNum, fsFromMark, 0, toRead, toFill, &actualCount);
  +        bytesRead = actualCount;
  +    }
  +    else
  +    {
  +        long byteCount = toRead;
  +        err = FSRead(mFileRefNum, &byteCount, toFill);
  +        bytesRead = byteCount;
  +    }
  +    
  +    if (err != noErr && err != eofErr)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotReadFromFile);
  +    
  +    return bytesRead;
   }
   
   
  -void XMLMacFile::reset()
  +void
  +XMLMacFile::reset()
   {
  -    if (!valid)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::resetFile -- Not a valid file");
  -    if (noErr != SetFPos(fileRef, fsFromStart, 0))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::fileSize -- Error closing file");
  +    OSErr err = noErr;
  +    
  +    if (!mFileValid)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile);
  +    
  +    if (gHasHFSPlusAPIs)
  +        err = FSSetForkPosition(mFileRefNum, fsFromStart, 0);
  +    else
  +        err = SetFPos(mFileRefNum, fsFromStart, 0);
  +    
  +    if (err != noErr)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotResetFile);
   }
   
  +
   XMLMacFile::~XMLMacFile()
   {
  -    if (valid)
  +    if (mFileValid)
           close();
   }
   
  +
   // ---------------------------------------------------------------------------
  -//  Local methods
  +//  XMLPlatformUtils: The panic method
   // ---------------------------------------------------------------------------
  -static void WriteCharStrStdErr(const char* const toWrite)
  -{
  -    // Just print the data out the the MetroWerks standard error.
  -    cerr << toWrite;
  -}
  -
  -
  -static void WriteCharStrStdOut(const char* const toWrite)
  -{
  -    // Just print the data out the the MetroWerks standard error.
  -    cout << toWrite;
  -}
  -
  -
  -static void WriteUStrStdErr(const XMLCh* const toWrite)
  -{
  -    // Oh well, got to do it the hard way
  -    char* tmpVal = XMLString::transcode(toWrite);
  -    ArrayJanitor<char> janTmp(tmpVal);
  -    WriteCharStrStdErr(tmpVal);
  -}
  -
  -
  -static void WriteUStrStdOut(const XMLCh* const toWrite)
  +void XMLPlatformUtils::panic(const PanicReasons reason)
   {
  -    // Oh well, got to do it the hard way
  -    char* tmpVal = XMLString::transcode(toWrite);
  -    ArrayJanitor<char> janTmp(tmpVal);
  -    WriteCharStrStdOut(tmpVal);
  +    const char* reasonStr = "Unknown reason";
  +    if (reason == Panic_NoTransService)
  +        reasonStr = "Could not load a transcoding service";
  +    else if (reason == Panic_NoDefTranscoder)
  +        reasonStr = "Could not load a local code page transcoder";
  +    else if (reason == Panic_CantFindLib)
  +        reasonStr = "Could not find the xerces-c DLL";
  +    else if (reason == Panic_UnknownMsgDomain)
  +        reasonStr = "Unknown message domain";
  +    else if (reason == Panic_CantLoadMsgDomain)
  +        reasonStr = "Cannot load message domain";
  +    else if (reason == Panic_SynchronizationErr)
  +        reasonStr = "A system synchronization error occured";
  +    else if (reason == Panic_SystemInit)
  +        reasonStr = "Failed to complete platform dependent initialization";
  +    else
  +        reasonStr = "Unknown error source";
  +    
  +    //
  +    //  This isn't real friendly and should be cleaned up.
  +    // Replace this code to do whatever you need to do.
  +    //
  +    char text[200];
  +    sprintf(text, "Xerces Panic Error: %s", reasonStr);
  +    
  +    Str255 pasText;
  +    CopyCStringToPascal(text, pasText);
  +    DebugStr(pasText);
  +    
  +    exit(-1);
   }
   
   
  -
   // ---------------------------------------------------------------------------
   //  XMLPlatformUtils: File Methods
   // ---------------------------------------------------------------------------
  @@ -422,56 +382,41 @@
       return theFile->size();
   }
   
  +
   FileHandle XMLPlatformUtils::openFile(const char* const fileName)
   {
  -     FileHandle file = 0;
  -     int isRes = 0;
  -     
  -    // Check to make sure the file system is in a state where we can use it     
  -     if (!gFileSystemReady)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile(const char* const) -- File system not ready."
  -                  "  Maybe missing gestalt or no support for FSSpec's.");
  -                  
  -    if (strlen(fileName) >= strlen(resBaseStr))
  -        if (strstr(fileName, resBaseStr) == fileName)
  -            isRes = 1;
  -            
  -    if (isRes == 0)
  -    {
  -        file = new XMLMacFile();
  -        file->open(fileName);
  -    }
  -    else
  -    {
  -        file = new XMLResFile();
  -        file->open(&fileName[strlen(resBaseStr)]);
  -    }
  -    if (file == 0)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::openFile(const char* const) -- Failed to allocate file object.");
  -    return file;
  +    const XMLCh* xmlPath = XMLString::transcode(fileName);
  +    ArrayJanitor<const XMLCh> jan(xmlPath);
  +    return openFile(xmlPath);
   }
   
  +
   FileHandle XMLPlatformUtils::openFile(const XMLCh* const fileName)
   {
  -    char* tmpName = XMLString::transcode(fileName);
  -    FileHandle retVal = openFile(tmpName);
  -    delete [] tmpName;
  -
  -    return retVal;
  +    // Check to make sure the file system is in a state where we can use it
  +    if (!gFileSystemCompatible)
  +        ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotOpenFile);
  +    
  +    XMLMacFile* file = new XMLMacFile();
  +    Janitor<XMLMacAbstractFile> janFile(file);
  +    file->open(fileName);
  +    janFile.orphan();
  +    
  +    return file;
   }
   
   
   FileHandle XMLPlatformUtils::openStdInHandle()
   {
  -    throw XMLPlatformUtilsException("XMLPlatformUtils::openStdInHandle -- Standard input not supported on MacOS");
  -    return NULL;//(void*)&cin;
  +    ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_CouldNotOpenFile);
  +    return NULL;
   }
   
   
   unsigned int
   XMLPlatformUtils::readFileBuffer(   const   FileHandle      theFile
  -                                    , const unsigned int    toRead
  -                                    ,       XMLByte* const  toFill)
  +                                 , const unsigned int    toRead
  +                                 ,       XMLByte* const  toFill)
   {
       return theFile->read(toRead, toFill);
   }
  @@ -482,251 +427,247 @@
       theFile->reset();
   }
   
  +
   // ---------------------------------------------------------------------------
  -//  XMLPlatformUtils: File Methods
  +//  XMLPlatformUtils: File system methods
   // ---------------------------------------------------------------------------
  -void XMLPlatformUtils::writeToStdErr(const XMLCh* const toWrite)
  -{
  -    WriteUStrStdErr(toWrite);
  -}
  -
  -void XMLPlatformUtils::writeToStdErr(const char* const toWrite)
  +XMLCh* XMLPlatformUtils::getFullPath(const XMLCh* const srcPath)
   {
  -    WriteCharStrStdErr(toWrite);
  +    XMLCh* path = NULL;
  +    
  +    if (gHasHFSPlusAPIs)
  +    {
  +        FSRef ref;
  +        if (!XMLParsePathToFSRef(srcPath, ref) || (path = XMLCreateFullPathFromRef(ref)) == NULL)
  +            path = XMLString::replicate(srcPath);
  +    }
  +    else
  +    {
  +        FSSpec spec;
  +        if (!XMLParsePathToFSSpec(srcPath, spec) || (path = XMLCreateFullPathFromSpec(spec)) == NULL)
  +            path = XMLString::replicate(srcPath);
  +    }
  +    
  +    return path;
   }
   
  -void XMLPlatformUtils::writeToStdOut(const XMLCh* const toWrite)
  -{
  -    WriteUStrStdOut(toWrite);
  -}
   
  -void XMLPlatformUtils::writeToStdOut(const char* const toWrite)
  +bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck)
   {
  -    WriteCharStrStdOut(toWrite);
  +    return (toCheck[0] != L'/');
   }
   
   
   
  -// ---------------------------------------------------------------------------
  -//  XMLPlatformUtils: Platform methods
  -// ---------------------------------------------------------------------------
  -XMLCh* XMLPlatformUtils::getBasePath(const XMLCh* const srcPath)
  -{
  -    char* workingPath = XMLString::transcode(srcPath);
  -    XMLCh *result;
  -    char dirSep = '/', *lastSep = 0;
  +XMLCh* XMLPlatformUtils::weavePaths(const   XMLCh* const    basePath
  +                                    , const XMLCh* const    relativePath)
  +                                    
  +{
  +    // Code from Windows largely unmodified for the Macintosh,
  +    // with the exception of removing support for '\' path
  +    // separator.
  +    //
  +    // Note that there is no support currently for Macintosh
  +    // path separators ':'.
  +    
  +    // Create a buffer as large as both parts and empty it
  +    XMLCh* tmpBuf = new XMLCh[XMLString::stringLen(basePath)
  +        + XMLString::stringLen(relativePath)
  +        + 2];
  +    ArrayJanitor<XMLCh> janBuf(tmpBuf);
  +    *tmpBuf = 0;
  +    
  +    //
  +    //  If we have no base path, then just take the relative path as
  +    //  is.
  +    //
  +    if (!basePath)
  +    {
  +        XMLString::copyString(tmpBuf, relativePath);
  +        janBuf.orphan();
  +        return tmpBuf;
  +    }
       
  -    for(int i = 0; workingPath && workingPath[i]; i++)
  -        if (workingPath[i] == dirSep)
  -            lastSep = &workingPath[i];
  -            
  -    if (lastSep == 0)
  -        return XMLString::transcode("");
  -        
  -    lastSep++;
  -    dirSep = *lastSep;
  -    *lastSep = 0;
  -//    cout << "Returning base path: " << workingPath << endl;
  -    result = XMLString::transcode(workingPath);
  -    *lastSep = dirSep;
  -    delete [] workingPath;
  -
  -    return result;    
  -}
  -
  -bool XMLPlatformUtils::isRelative(const XMLCh* const toCheck)
  -{
  -    char* workingPath = XMLString::transcode(toCheck);
  -    char dirSep = '/', *sep;
  -    short refNum;
  -    long freeSpace;
  -    unsigned char volName[260];
  +    if (!*basePath)
  +    {
  +        XMLString::copyString(tmpBuf, relativePath);
  +        janBuf.orphan();
  +        return tmpBuf;
  +    }
       
  -    if (!*workingPath)
  -        return false;
  +    const XMLCh* basePtr = basePath + (XMLString::stringLen(basePath) - 1);
  +    if (*basePtr != chForwardSlash)
  +    {
  +        while ((basePtr >= basePath) && (*basePtr != chForwardSlash))
  +            basePtr--;
  +    }
  +    
  +    // There is no relevant base path, so just take the relative part
  +    if (basePtr < basePath)
  +    {
  +        XMLString::copyString(tmpBuf, relativePath);
  +        janBuf.orphan();
  +        return tmpBuf;
  +    }
  +    
  +    
  +    //  We have some path part, so we need to check to see if we have to
  +    //  weave any of the parts together.
  +    const XMLCh* pathPtr = relativePath;
       
  -    if (strstr(workingPath, ":"))
  -        dirSep = ':';
  +    while (true)
  +    {
  +        // If it does not start with some period, then we are done
  +        if (*pathPtr != chPeriod)
  +            break;
           
  -    if ( dirSep == '/' && workingPath[0] == '/')
  -        return false;
  -    if ( dirSep == '/' && workingPath[0] != '/')
  -        return true;
  +        unsigned int periodCount = 1;
  +        pathPtr++;
  +        if (*pathPtr == chPeriod)
  +        {
  +            pathPtr++;
  +            periodCount++;
  +        }
           
  -    sep = strstr(workingPath, ":");
  -    if (sep == 0)
  -        return true;
  +        // Has to be followed by a / or the null to mean anything
  +        if ((*pathPtr != chForwardSlash) &&  *pathPtr)
  +            break;
           
  -    dirSep = *sep;
  -    *sep = 0;
  -    
  -    for(short i = 0; i < 7; i++)
  -    {
  -        if ( noErr == GetVInfo(i, volName, &refNum, &freeSpace))
  +        if (*pathPtr)
  +            pathPtr++;
  +        
  +        // If it's one period, just eat it, else move backwards in the base
  +        if (periodCount == 2)
           {
  -            if (strlen(workingPath) != volName[0])
  -                continue;
  -                
  -            for(int j = 0, refNum = 0; j < volName[0]; j++)
  -                if (workingPath[j] != volName[j+1])
  -                    refNum = 1;
  -                    
  -            if (!refNum)
  -            {
  -                *sep = dirSep;
  -                delete [] workingPath;
  -                return false;
  -            }
  +            basePtr--;
  +            while ((basePtr >= basePath) && (*basePtr != chForwardSlash))
  +                basePtr--;
  +            
  +            // The base cannot provide enough levels, so it's in error/
  +            if (basePtr < basePath)
  +                ThrowXML(XMLPlatformUtilsException, XMLExcepts::File_BasePathUnderflow);
           }
       }
  -    *sep = dirSep;
  -    delete [] workingPath;
  -    return true;
  +    
  +    // Copy the base part up to the base pointer
  +    XMLCh* bufPtr = tmpBuf;
  +    const XMLCh* tmpPtr = basePath;
  +    while (tmpPtr <= basePtr)
  +        *bufPtr++ = *tmpPtr++;
  +    
  +    // And then copy on the rest of our path
  +    XMLString::copyString(bufPtr, pathPtr);
  +    
  +    // Orphan the buffer and return it
  +    janBuf.orphan();
  +    return tmpBuf;
   }
   
   
  -
   // ---------------------------------------------------------------------------
   //  XMLPlatformUtils: Timing Methods
   // ---------------------------------------------------------------------------
   unsigned long XMLPlatformUtils::getCurrentMillis()
   {
  -    return TickCount()*10;
  +    return TickCount() * 100 / 6;
   }
   
   
   
   // ---------------------------------------------------------------------------
   //  Mutex methods
  +//
  +// There are a number of choices for multi-threading on Mac OS. Traditionally
  +// there was the Thread Manager, which provided cooperative multitasking on
  +// 68K and PPC platforms, and preemptive multitasking on 68K platforms only.
  +// The primary threading model supported under Carbon is the Multiprocessing
  +// library, which as of version 2.0 provides a nice set of primitives. Under
  +// Mac OS X, the Multiprocessing library is a thin veneer over pthreads.
  +//
  +// For lack of any really good solutions, I've implemented these mutexes
  +// atop the Multiprocessing library. The critical regions employed here
  +// support recursive behavior, which is required by Xerces.
  +//
  +// Please note that, despite this implementation, there are probably other
  +// MacOS barriers to actually using Xerces in a multi-threaded environment.
  +// Many other parts of your system and/or development environment may not
  +// support pre-emption, even under Mac OS X. Examples may include the memory
  +// allocator, the Unicode Converter or Utilities, and perhaps the file
  +// system (though the FS is better with Multiprocessing as of System 9.0).
  +//
  +// These routines are provided somewhat speculatively, and with the philosphy
  +// that this code, at least, shouldn't be the reason why multithreading
  +// doesn't work. Compatibility of this library wrt the other areas described
  +// above will be resolved in time.
   // ---------------------------------------------------------------------------
  -void XMLPlatformUtils::closeMutex(void* const mtxHandle)
  -{
  -    if (!MPLibraryIsLoaded())
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::makeMutex -- Multiprocessing library not installed correctly.  Please Install");
   
  -    MPSemaphoreID *sema = (MPSemaphoreID*)mtxHandle;
  -    if (!sema) return;
  -        
  -    if (noErr != MPDeleteSemaphore(*sema))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::closeMutex -- Error deleting semaphore");
  +void* XMLPlatformUtils::makeMutex()
  +{
  +    MPCriticalRegionID criticalRegion = NULL;
  +    OSStatus status = MPCreateCriticalRegion(&criticalRegion);
  +    return (status == noErr) ? static_cast<void*>(criticalRegion) : NULL;
   }
   
   
  -void XMLPlatformUtils::lockMutex(void* const mtxHandle)
  +void XMLPlatformUtils::closeMutex(void* const mtxHandle)
   {
  -    if (!MPLibraryIsLoaded())
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::makeMutex -- Multiprocessing library not installed correctly.  Please Install");
  -
  -    MPSemaphoreID *sema = (MPSemaphoreID*)mtxHandle;
  -    if (!sema) return;
  -    
  -    if (noErr != MPWaitOnSemaphore(*sema, -1))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::lockMutex -- Error locking semaphore");
  +    MPCriticalRegionID criticalRegion = reinterpret_cast<MPCriticalRegionID>(mtxHandle);
  +    OSStatus status = MPDeleteCriticalRegion(criticalRegion);
   }
   
   
  -void* XMLPlatformUtils::makeMutex()
  +void XMLPlatformUtils::lockMutex(void* const mtxHandle)
   {
  -    if (!MPLibraryIsLoaded())
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::makeMutex -- Multiprocessing library not installed correctly.  Please Install");
  -        
  -    MPSemaphoreID *result = new MPSemaphoreID;
  -    if (!result)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::makeMutex -- Error allocating memory for a semaphore");
  -    
  -    if (noErr != MPCreateBinarySemaphore(result))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::makeMutex -- Error Creating semaphore");
  -        
  -    return (void*)result;
  +    MPCriticalRegionID criticalRegion = reinterpret_cast<MPCriticalRegionID>(mtxHandle);
  +    OSStatus status = MPEnterCriticalRegion(criticalRegion, kDurationForever);
   }
   
   
   void XMLPlatformUtils::unlockMutex(void* const mtxHandle)
   {
  -    if (!MPLibraryIsLoaded())
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::makeMutex -- Multiprocessing library not installed correctly.  Please Install");
  -
  -    MPSemaphoreID *sema = (MPSemaphoreID*)mtxHandle;
  -    if (!sema) return;
  -    
  -    if (noErr != MPSignalSemaphore(*sema))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::unlockMutex -- Error unlocking semaphore");
  +    MPCriticalRegionID criticalRegion = reinterpret_cast<MPCriticalRegionID>(mtxHandle);
  +    OSStatus status = MPExitCriticalRegion(criticalRegion);
   }
   
   
   // ---------------------------------------------------------------------------
   //  Miscellaneous synchronization methods
  +//
  +// Atomic manipulation is implemented atop routines that were traditionally
  +// part of DriverServices, but are now apparently a part of Carbon. If this
  +// selection proves to be invalid, similar routines in OpenTransport could
  +// be used instead.
   // ---------------------------------------------------------------------------
  +
   void*
   XMLPlatformUtils::compareAndSwap(       void**      toFill
  -                                , const void* const newValue
  -                                , const void* const toCompare)
  +                                 , const void* const newValue
  +                                 , const void* const toCompare)
   {
  -    // Note -- I'm note sure what this method is supposed to do.  I just copied
  -    // the code from the linux utils.
  +    // Replace *toFill with newValue iff *toFill == toCompare,
  +    // returning previous value of *toFill
       
  -    void *retVal = *toFill;
  -    if (*toFill == toCompare)
  -              *toFill = (void *)newValue;
  -    return retVal;
  +    Boolean success = CompareAndSwap(
  +        reinterpret_cast<UInt32>(toCompare),
  +        reinterpret_cast<UInt32>(newValue),
  +        reinterpret_cast<UInt32*>(toFill));
       
  -    throw XMLPlatformUtilsException("XMLPlatformUtils::compareAndSwap -- Not Implemented Yet.");
  +    return (success) ? const_cast<void*>(toCompare) : *toFill;
   }
   
   
   int XMLPlatformUtils::atomicIncrement(int &location)
   {
  -/*    if (!MPLibraryIsLoaded())
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::platformInit -- Multiprocessing library not installed correctly.  Please Install");
  -
  -    if (noErr != MPEnterCriticalRegion(gCriticalRegion, -1))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::atomicIncrement -- Failed to enter the critical region.");*/
  -    
  -    int result = location++;
  -    
  -/*    if (noErr != MPExitCriticalRegion(gCriticalRegion))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::atomicIncrement -- Failed to exit the critical region.");*/
  -        
  -    return result;
  +    return IncrementAtomic(reinterpret_cast<long*>(&location));
   }
   
   
   int XMLPlatformUtils::atomicDecrement(int &location)
   {
  -/*    if (!MPLibraryIsLoaded())
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::platformInit -- Multiprocessing library not installed correctly.  Please Install");
  -
  -    if (noErr != MPEnterCriticalRegion(gCriticalRegion, -1))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::atomicIncrement -- Failed to enter the critical region.");*/
  -    
  -    int result = location--;
  -    
  -/*    if (noErr != MPExitCriticalRegion(gCriticalRegion))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::atomicIncrement -- Failed to exit the critical region.");*/
  -        
  -    return result;
  +    return DecrementAtomic(reinterpret_cast<long*>(&location));
   }
   
  -// Routine to check to see if a system function is available
  -static bool MySWRoutineAvailable (int trapWord)
  -{
  -    TrapType trType;
   
  -    // first determine whether it is an Operating System or Toolbox routine
  -    if ((trapWord & 0x0800) == 0)
  -        trType = OSTrap;
  -    else
  -        trType = ToolTrap;
  -        
  -    // filter cases where older systems mask with 0x1FF rather than 0x3FF
  -    if (trType == ToolTrap && ((trapWord & 0x03FF) >= 0x200) &&
  -            (GetToolboxTrapAddress(0xA86E) == GetToolboxTrapAddress(0xAA6E)))
  -        return false;
  -    else
  -        return (NGetTrapAddress(trapWord, trType) !=
  -                    GetToolboxTrapAddress(_Unimplemented));
  -}
  -
   // ---------------------------------------------------------------------------
   //  XMLPlatformUtils: Private Static Methods
   // ---------------------------------------------------------------------------
  @@ -736,135 +677,767 @@
   //
   void XMLPlatformUtils::platformInit()
   {
  -    OSErr myErr;
  -    long feature;
  +    long value;
       
       // Figure out if we have the gestalt manager
  -    gGestaltAvail = MySWRoutineAvailable(_Gestalt);
  +    // --we better have by now...this is a pre-system 7 feature!
  +    gGestaltAvail =
  +#if TARGET_API_MAC_CARBON
  +        true;
  +#else
  +    TrapAvailable(_Gestalt);
  +#endif
       
  -    // Figure out if we have the FSspec function to use
  +    // Figure out which functions we have available
       if (gGestaltAvail)
       {
  -        myErr = Gestalt(gestaltFSAttr, &feature);
  -        if (myErr == noErr)
  +        if (Gestalt(gestaltFSAttr, &value) == noErr)
           {
  -            if (feature & gestaltHasFSSpecCalls)
  -                gFileSystemReady = true;
  +            gHasFSSpecAPIs = (value & gestaltHasFSSpecCalls) != 0;
  +            gHasFS2TBAPIs = (value & gestaltFSSupports2TBVols) != 0;
  +            gHasHFSPlusAPIs = (value & gestaltHasHFSPlusAPIs) != 0;
           }
       }
  +    
  +    gFileSystemCompatible = gHasFSSpecAPIs;
  +}
   
  -/*    if (!MPLibraryIsLoaded())
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::platformInit -- Multiprocessing library not installed correctly.  Please Install");
  -        
  -    if (noErr != MPCreateCriticalRegion(&gCriticalRegion))
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::platformInit -- Error creating critical section");*/
  +
  +//
  +//  This method handles the MacOS basic termination functions.
  +//
  +void XMLPlatformUtils::platformTerm()
  +{
  +}
  +
  +
  +// ---------------------------------------------------------------------------
  +//  XMLPlatformUtils: Private Static Methods
  +// ---------------------------------------------------------------------------
  +
  +//
  +//  This method is called by the platform independent part of this class
  +//  during initialization. We have to create the type of net accessor that
  +//  we want to use. If none, then just return zero.
  +//
  +XMLNetAccessor* XMLPlatformUtils::makeNetAccessor()
  +{
  +    // No net accessor on the Mac for now.
  +    //
  +    // We could:
  +    //  Use URLAccess under Carbon and >= 8.6
  +    //  Use libwww on Mac OS X
  +    return 0;
   }
   
  +
   //
  -//  This is the first thing called during init. Each platform needs to set
  -//  up the path to the Internationalization code.
  +//  This method is called by the platform independent part of this class
  +//  when client code asks to have one of the supported message sets loaded.
  +//
  +XMLMsgLoader* XMLPlatformUtils::loadAMsgSet(const XMLCh* const msgDomain)
  +{
  +    return new InMemMsgLoader(msgDomain);
  +}
  +
  +
   //
  -//  NOTE:   It CANNOT use an String class methods, because that class has not
  -//          be set up yet.
  +//  This method is called very early in the bootstrapping process. This guy
  +//  must create a transcoding service and return it. It cannot use any string
  +//  methods, any transcoding services, throw any exceptions, etc... It just
  +//  makes a transcoding service and returns it, or returns zero on failure.
   //
  -void XMLPlatformUtils::setupIntlPath()
  +XMLTransService* XMLPlatformUtils::makeTransService()
  +{
  +    return new MacOSUnicodeConverter;
  +}
  +
  +
  +//---------------------------------------------------
  +// Utility Functions
  +//---------------------------------------------------
  +
  +// Routine to check to see if a system function is available
  +#if !TARGET_API_MAC_CARBON
  +static bool
  +TrapAvailable (UInt16 trapWord)
  +{
  +    TrapType trType;
  +    
  +    // first determine whether it is an Operating System or Toolbox routine
  +    if ((trapWord & 0x0800) == 0)
  +        trType = OSTrap;
  +    else
  +        trType = ToolTrap;
  +    
  +    // filter cases where older systems mask with 0x1FF rather than 0x3FF
  +    if (trType == ToolTrap && ((trapWord & 0x03FF) >= 0x200) &&
  +        (GetToolboxTrapAddress(0xA86E) == GetToolboxTrapAddress(0xAA6E)))
  +        return false;
  +    else
  +        return (NGetTrapAddress(trapWord, trType) !=
  +        GetToolboxTrapAddress(_Unimplemented));
  +}
  +#endif
  +
  +
  +bool
  +XMLParsePathToFSRef(const XMLCh* const pathName, FSRef& ref)
   {
  -//    fgIntlPath = "Macintosh HD:Desktop Folder:xml4csrc2_2_0:intlFiles:data:locales:";
  -    short fileRef;
  -    unsigned char pStr[300];
  -    OSErr myErr;
  -    OSType textCode = 'TEXT';
  -//    StandardFileReply result;
  -//    FInfo fileInfo;    
  -    long feature;
  +    const XMLCh* p = pathName;
  +    const XMLCh* pEnd;
       
  -    if (fgIntlPath != 0)
  -        return;
  +    OSErr err = noErr;
  +    
  +    if (*p == L'/')
  +    {
  +        // Absolute name: grab the first component as volume name
           
  -    // Figure out if we have the gestalt manager
  -    gGestaltAvail = MySWRoutineAvailable(_Gestalt);
  +        // Find the end of the path segment
  +        for (pEnd = ++p; *pEnd && *pEnd != L'/'; ++pEnd) ;
  +        size_t segLen = pEnd - p;
  +        
  +        // Try to find a volume that matches this name
  +        for (ItemCount volIndex = 1; err == noErr; ++volIndex)
  +        {
  +            HFSUniStr255 hfsStr;
  +            hfsStr.length = 0;
  +            
  +            // Get the volume name
  +            err = FSGetVolumeInfo(
  +                0,
  +                volIndex,
  +                static_cast<FSVolumeRefNum*>(NULL),
  +                0,
  +                static_cast<FSVolumeInfo*>(NULL),
  +                &hfsStr,
  +                &ref
  +                );
  +            
  +            // Compare against our path segment
  +            if (err == noErr && segLen == hfsStr.length)
  +            {
  +                const UniChar* a = hfsStr.unicode;
  +                const XMLCh* b = p;
  +                while (b != pEnd && *a == *b)
  +                {
  +                    ++a;
  +                    ++b;
  +                }
  +                
  +                if (b == pEnd)
  +                    break;  // we found our volume
  +            }
  +        }
  +        
  +        p = pEnd;
  +    }
  +    else
  +    {
  +        // Relative name, so get the default directory as parent ref
  +        FSSpec spec;
  +        err = FSMakeFSSpec(0, 0, NULL, &spec);
  +        if (err == noErr)
  +            err = FSpMakeFSRef(&spec, &ref);
  +    }
       
  -    // Figure out if we have the FSspec function to use
  -    if (gGestaltAvail)
  +    // ref now refers to the a parent directory: parse the rest of the path
  +    while (err == noErr && *p)
       {
  -        myErr = Gestalt(gestaltFSAttr, &feature);
  -        if (myErr == noErr)
  +        switch (*p)
           {
  -            if (feature & gestaltHasFSSpecCalls)
  -                gFileSystemReady = true;
  +        case L'/':   // Just skip any number of path separators
  +            ++p;
  +            break;
  +            
  +        case L'.':   // Potentially "current directory" or "parent directory"
  +            if (p[1] == L'/' || p[1] == 0)       // "current directory"
  +            {
  +                ++p;
  +                break;
  +            }
  +            else if (p[1] == L'.' && (p[2] == L'/' || p[2] == 0)) // "parent directory"
  +            {
  +                p += 2;  // Get the parent of our parent
  +                
  +                FSCatalogInfo catalogInfo;
  +                err = FSGetCatalogInfo(
  +                    &ref,
  +                    kFSCatInfoParentDirID,
  +                    &catalogInfo,
  +                    static_cast<HFSUniStr255*>(NULL),
  +                    static_cast<FSSpec*>(NULL),
  +                    &ref
  +                    );
  +                
  +                // Check that we didn't go too far
  +                if (err != noErr || catalogInfo.parentDirID == fsRtParID)
  +                    return false;
  +                
  +                break;
  +            }
  +            else // some other sequence of periods...fall through and treat as segment
  +                ;
  +            
  +        default:
  +            // Find the end of the path segment
  +            for (pEnd = p; *pEnd && *pEnd != L'/'; ++pEnd) ;
  +            
  +            // pEnd now points either to '/' or NUL
  +            // Create a new ref using this path segment
  +            err = FSMakeFSRefUnicode(
  +                &ref,
  +                pEnd - p,
  +                reinterpret_cast<UniChar*>(const_cast<XMLCh*>(p)),
  +                kTextEncodingUnknown,
  +                &ref
  +                );
  +            
  +            p = pEnd;
  +            break;
           }
       }
  +    
  +    return err == noErr;
  +}
   
  -    // Check to make sure the file system is in a state where we can use it
  -    if (!gFileSystemReady)
  -        throw XMLPlatformUtilsException("XMLPlatformUtils::setupIntlPath -- File system not ready."
  -                  "  Maybe missing gestalt or no support for FSSpec's.");
   
  -    if (noErr == HOpenDF(0, 0, "\p:locales:convrtrs.txt", fsRdWrPerm, &fileRef))
  +bool
  +XMLParsePathToFSSpec(const XMLCh* const pathName, FSSpec& spec)
  +{
  +    // Transcode the path into ascii
  +    const char* p = XMLString::transcode(pathName);
  +    ArrayJanitor<const char> janPath(p);
  +    const char* pEnd;
  +    
  +    OSErr err = noErr;
  +    Str255 name;  // Must be long enough for a partial pathname consisting of two segments (64 bytes)
  +    
  +    if (*p == '/')
       {
  -        if (noErr != FSClose(fileRef))
  -            throw XMLPlatformUtilsException("XMLPlatformUtils::setupIntlPath -- ERROR");
  +        // Absolute name: grab the first component as volume name
  +        
  +        // Find the end of the path segment
  +        for (pEnd = ++p; *pEnd && *pEnd != '/'; ++pEnd) ;
  +        size_t segLen = pEnd - p;
  +        
  +        // Try to find a volume that matches this name
  +        for (ItemCount volIndex = 1; err == noErr; ++volIndex)
  +        {
  +            FSVolumeRefNum volRefNum;
               
  -        fgIntlPath = ":locales:";
  -        return;
  +            if (gHasFS2TBAPIs)
  +            {
  +                XVolumeParam xVolParam;
  +                name[0] = 0;
  +                xVolParam.ioNamePtr  = name;
  +                xVolParam.ioVRefNum  = 0;
  +                xVolParam.ioXVersion = 0;
  +                xVolParam.ioVolIndex = volIndex;
  +                err = PBXGetVolInfoSync(&xVolParam);
  +                volRefNum = xVolParam.ioVRefNum;
  +            }
  +            else
  +            {
  +#if !TARGET_API_MAC_CARBON
  +                HParamBlockRec hfsParams;
  +                name[0] = 0;
  +                hfsParams.volumeParam.ioNamePtr  = name;
  +                hfsParams.volumeParam.ioVRefNum  = 0;
  +                hfsParams.volumeParam.ioVolIndex = volIndex;
  +                err = PBHGetVInfoSync(&hfsParams);
  +                volRefNum = hfsParams.volumeParam.ioVRefNum;
  +#else
  +                err = nsvErr;
  +#endif
  +            }
  +            
  +            // Compare against our path segment
  +            if (err == noErr && segLen == StrLength(name))
  +            {
  +                ConstStringPtr a = name + 1;
  +                const char* b = p;
  +                while (b != pEnd && (*a == *b))
  +                {
  +                    ++a;
  +                    ++b;
  +                }
  +                
  +                if (b == pEnd)
  +                {
  +                    // we found our volume: fill in the spec
  +                    err = FSMakeFSSpec(volRefNum, fsRtDirID, NULL, &spec);
  +                    break;
  +                }
  +            }
  +        }
  +        
  +        p = pEnd;
       }
  +    else
  +    {
  +        // Relative name, so get the default directory as parent spec
  +        err = FSMakeFSSpec(0, 0, NULL, &spec);
  +    }
       
  -    throw XMLPlatformUtilsException("XMLPlatformUtils::setupIntlPath -- Couldn't find data files");
  -/*    if (noErr != StandardGetFile("\pPlease locate the convrtrs.txt file in the locales directory:", 0, 1, &textCode, &result))
  -            throw XMLPlatformUtilsException("XMLPlatformUtils::setupIntlPath -- StandardGetFile failed");
  +    // We now have a parent directory in the spec.
  +    while (err == noErr && *p)
  +    {
  +        switch (*p)
  +        {
  +        case '/':   // Just skip any number of path separators
  +            ++p;
  +            break;
               
  -    if (result.sfGood == 0)
  -            throw XMLPlatformUtilsException("XMLPlatformUtils::setupIntlPath -- failed to locate locale files");
  +        case L'.':   // Potentially "current directory" or "parent directory"
  +            if (p[1] == '/' || p[1] == 0)      // "current directory"
  +            {
  +                ++p;
  +                break;
  +            }
  +            else if (p[1] == '.' && (p[2] == '/' || p[2] == 0)) // "parent directory"
  +            {
  +                p += 2;  // Get the parent of our parent
  +                
  +                CInfoPBRec catInfo;
  +                catInfo.dirInfo.ioNamePtr = NULL;
  +                catInfo.dirInfo.ioVRefNum = spec.vRefNum;
  +                catInfo.dirInfo.ioFDirIndex = -1;
  +                catInfo.dirInfo.ioDrDirID = spec.parID;
  +                err = PBGetCatInfoSync(&catInfo);
  +                
  +                // Check that we didn't go too far
  +                if (err != noErr || catInfo.dirInfo.ioDrParID == fsRtParID)
  +                    return false;
  +                
  +                // Update our spec
  +                if (err == noErr)
  +                    err = FSMakeFSSpec(spec.vRefNum, catInfo.dirInfo.ioDrParID, NULL, &spec);
  +                
  +                break;
  +            }
  +            else // some other sequence of periods...fall through and treat as segment
  +                ;
               
  -    fgIntlPath = new char[result.sfFile.[0]+1];
  -    fgIntlPath[result.sfFile.[0]] = 0;
  -    memcpy(fgIntlPath, result.sfFile., result.sfFile.[0]);
  -    cout << fgIntlPath << endl;*/
  -            //throw XMLPlatformUtilsException("XMLPlatformUtils::setupIntlPath -- failed to load file info");
  +        default:
  +            {
  +                // Find the end of the path segment
  +                for (pEnd = p; *pEnd && *pEnd != '/'; ++pEnd) ;
  +                
  +                // Check for name length overflow
  +                if (pEnd - p > 31)
  +                    return false;
  +                
  +                // Make a partial pathname from our current spec to the new object
  +                unsigned char* partial = &name[1];
  +                
  +                *partial++ = ':';       // Partial leads with :
  +                const unsigned char* specName = spec.name; // Copy in spec name
  +                for (int specCnt = *specName++; specCnt > 0; --specCnt)
  +                    *partial++ = *specName++;
  +                
  +                *partial++ = ':';       // Separator
  +                while (p != pEnd)       // Copy in new element
  +                    *partial++ = *p++;
  +                
  +                name[0] = partial - &name[1];    // Set the name length
  +                
  +                // Update the spec
  +                err = FSMakeFSSpec(spec.vRefNum, spec.parID, name, &spec);
  +            }
  +            break;
  +        }
  +    }
  +    
  +    return err == noErr;
   }
   
  -// These functions are needed because MacOS doesn't define them
  -// even though they are used.
  -// Compare lexigraphically two strings
  -static char tolower(char c)
  -{
  -    if (c >= 'A' && c <= 'Z')
  -        return c + 'a' - 'A';
  -    return c;
  -}
   
  -int stricmp(const char *s1, const char *s2)
  +XMLCh*
  +XMLCreateFullPathFromRef(const FSRef& startingRef)
   {
  -    char c1, c2;
  -    while (1)
  +    OSErr err = noErr;
  +    FSCatalogInfo catalogInfo;
  +    HFSUniStr255 name;
  +    FSRef ref = startingRef;
  +    
  +    const size_t kBufSize = 512;
  +    XMLCh buf[kBufSize];
  +    size_t bufPos   = kBufSize;
  +    size_t bufCnt   = 0;
  +    
  +    XMLCh* result = NULL;
  +    size_t resultLen = 0;
  +    
  +    buf[--bufPos] = L'\0';
  +    ++bufCnt;
  +    
  +    try  // help in cleaning up since ArrayJanitor doesn't handle assignment ;(
       {
  -        c1 = tolower(*s1++);
  -        c2 = tolower(*s2++);
  -        if (c1 < c2) return -1;
  -        if (c1 > c2) return 1;
  -        if (c1 == 0) return 0;
  +        do
  +        {
  +            err = FSGetCatalogInfo(
  +                &ref,
  +                kFSCatInfoParentDirID,
  +                &catalogInfo,
  +                &name,
  +                static_cast<FSSpec*>(NULL),
  +                &ref
  +                );
  +            
  +            if (err == noErr)
  +            {
  +                // If there's not room in our static buffer for the new
  +                // name plus separator, dump it to the dynamic result buffer.
  +                if (bufPos < name.length + 1)
  +                {
  +                    XMLCh* temp = new XMLCh[bufCnt + resultLen];
  +                    
  +                    // Copy in the static buffer
  +                    memcpy(temp, &buf[bufPos], bufCnt * sizeof(XMLCh));
  +                    
  +                    // Copy in the old buffer
  +                    if (resultLen > 0)
  +                        memcpy(temp + bufCnt, result, resultLen);
  +                    
  +                    delete [] result;
  +                    result = temp;
  +                    resultLen += bufCnt;
  +                    
  +                    bufPos = kBufSize;
  +                    bufCnt = 0;
  +                }
  +                
  +                // Prepend our new name and a '/'
  +                bufPos -= name.length;
  +                memcpy(&buf[bufPos], name.unicode, name.length * sizeof(UniChar));
  +                buf[--bufPos] = L'/';
  +                bufCnt += (name.length + 1);
  +            }
  +        }
  +        while (err == noErr && catalogInfo.parentDirID != fsRtParID);
  +        
  +        // Composite existing buffer with any previous result buffer
  +        XMLCh* temp = new XMLCh[bufCnt + resultLen];
  +        
  +        // Copy in the static buffer
  +        memcpy(temp, &buf[bufPos], bufCnt * sizeof(XMLCh));
  +        
  +        // Copy in the old buffer
  +        if (resultLen > 0)
  +            memcpy(temp + bufCnt, result, resultLen * sizeof(XMLCh));
  +        
  +        delete [] result;
  +        result = temp;
  +    }
  +    catch (...)
  +    {
  +        delete [] result;
  +        throw;
       }
  +    
  +    return result;
   }
   
  -// Compare lexigraphically two strings up to a max length
   
  -int strnicmp(const char *s1, const char *s2, int n)
  +XMLCh*
  +XMLCreateFullPathFromSpec(const FSSpec& startingSpec)
   {
  -    int i;
  -    char c1, c2;
  -    for (i=0; i<n; i++)
  +    OSErr err = noErr;
  +    FSSpec spec = startingSpec;
  +    
  +    const size_t kBufSize = 512;
  +    char buf[kBufSize];
  +    size_t bufPos   = kBufSize;
  +    size_t bufCnt   = 0;
  +    
  +    char* result = NULL;
  +    size_t resultLen = 0;
  +    
  +    buf[--bufPos] = '\0';
  +    ++bufCnt;
  +    
  +    try  // help in cleanup since array janitor can't handle assignment ;(
       {
  -        c1 = tolower(*s1++);
  -        c2 = tolower(*s2++);
  -        if (c1 < c2) return -1;
  -        if (c1 > c2) return 1;
  -        if (!c1) return 0;
  +        short index = 0;
  +        do
  +        {
  +            CInfoPBRec catInfo;
  +            catInfo.dirInfo.ioNamePtr = spec.name;
  +            catInfo.dirInfo.ioVRefNum = spec.vRefNum;
  +            catInfo.dirInfo.ioFDirIndex = index;
  +            catInfo.dirInfo.ioDrDirID = spec.parID;
  +            err = PBGetCatInfoSync(&catInfo);
  +            
  +            if (err == noErr)
  +            {
  +                size_t nameLen = StrLength(spec.name);
  +                
  +                // If there's not room in our static buffer for the new
  +                // name plus separator, dump it to the dynamic result buffer.
  +                if (bufPos < nameLen + 1)
  +                {
  +                    char* temp = new char[bufCnt + resultLen];
  +                    
  +                    // Copy in the static buffer
  +                    memcpy(temp, &buf[bufPos], bufCnt);
  +                    
  +                    // Copy in the old buffer
  +                    if (resultLen > 0)
  +                        memcpy(temp + bufCnt, result, resultLen);
  +                    
  +                    delete [] result;
  +                    result = temp;
  +                    resultLen += bufCnt;
  +                    
  +                    bufPos = kBufSize;
  +                    bufCnt = 0;
  +                }
  +                
  +                // Prepend our new name and a '/'
  +                bufPos -= nameLen;
  +                memcpy(&buf[bufPos], &spec.name[1], nameLen);
  +                buf[--bufPos] = '/';
  +                bufCnt += (nameLen + 1);
  +                
  +                // From here on out, ignore the input file name
  +                index = -1;
  +                
  +                // Move up to the parent
  +                spec.parID = catInfo.dirInfo.ioDrParID;
  +            }
  +        }
  +        while (err == noErr && spec.parID != fsRtParID);
  +        
  +        // Composite existing buffer with any previous result buffer
  +        char* temp = new char[bufCnt + resultLen];
  +        
  +        // Copy in the static buffer
  +        memcpy(temp, &buf[bufPos], bufCnt);
  +        
  +        // Copy in the old buffer
  +        if (resultLen > 0)
  +            memcpy(temp + bufCnt, result, resultLen);
  +        
  +        delete [] result;
  +        result = temp;
  +        resultLen += bufCnt;
       }
  -    return 0;
  +    catch (...)
  +    {
  +        delete [] result;
  +        throw;
  +    }
  +    
  +    // Cleanup and transcode to unicode
  +    ArrayJanitor<char> jan(result);
  +    return XMLString::transcode(result);
   }
   
  -void XMLPlatformUtils::platformTerm()
  +
  +/*
  +XMLResFile is pretty twisted and not currently used.
  +
  +static const char *resBaseStr = "/Access The Resource Fork Instead of the data fork?";
  +
  +
  +FileHandle XMLPlatformUtils::openFile(const char* const fileName)
   {
  -    // We don't have any termination requirements at this time
  +    FileHandle file = 0;
  +    int isRes = 0;
  +    
  +    // Check to make sure the file system is in a state where we can use it
  +    if (!gFileSystemReady)
  +        ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +    //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile(const char* const) -- File system not ready."
  +    //          "  Maybe missing gestalt or no support for FSSpec's.");
  +    
  +    if (strlen(fileName) >= strlen(resBaseStr))
  +        if (strstr(fileName, resBaseStr) == fileName)
  +            isRes = 1;
  +        
  +        if (isRes == 0)
  +        {
  +            file = new XMLMacFile();
  +            file->open(fileName);
  +        }
  +        else
  +        {
  +            file = new XMLResFile();
  +            file->open(&fileName[strlen(resBaseStr)]);
  +        }
  +        if (file == 0)
  +            ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +        //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile(const char* const) -- Failed to allocate file object.");
  +        return file;
   }
  +
  +
  +//----------------------------------------------------------------------------
  +// XMLResFile methods
  +//----------------------------------------------------------------------------
  +XMLResFile::XMLResFile();
  +
  +
  +void XMLResFile::open(const char* const resInfo)
  +{
  +    char option[32], value[32], command[70];
  +    int cmdEnd = 0, cmdStart = 0;
  +    int optEnd = 0, sep;
  +    int mode = -1;
  +    int typeValid = 0;
  +    
  +    if (!strchr(&resInfo[cmdStart], '/'))
  +        ThrowXML(XMLPlatformUtilsException, XML4CExcepts::URL_MalformedURL);
  +    
  +    while(resInfo[cmdEnd] != '/')
  +    {
  +        if (strchr(&resInfo[cmdStart], '&') < strchr(&resInfo[cmdStart], '/') && strchr(&resInfo[cmdStart], '&') != 0)
  +            cmdEnd = strchr(&resInfo[cmdStart], '&') - resInfo - 1;
  +        else
  +            cmdEnd = strchr(&resInfo[cmdStart], '/') - resInfo - 1;
  +        
  +        if (cmdEnd - cmdStart > 68)
  +            ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +        //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- resource option too long (>68 chars)");
  +        
  +        memcpy(command, &resInfo[cmdStart], cmdEnd - cmdStart + 1);
  +        command[cmdEnd - cmdStart + 1] = 0;
  +        if (!strchr(command, '='))
  +            ThrowXML(XMLPlatformUtilsException, XML4CExcepts::URL_MalformedURL);
  +        //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Malformed resource locater");
  +        
  +        sep = strchr(command, '=') - command;
  +        memcpy(option, command, sep);
  +        option[sep] = 0;
  +        memcpy(value, &command[sep+1], strlen(command) - sep);
  +        
  +        if (!strcmp(option, "mode"))
  +        {
  +            if (!strcmp(value, "by_id"))
  +                mode = 1;
  +            else if (!strcmp(value, "by_id1"))
  +                mode = 2;
  +            else if (!strcmp(value, "by_name"))
  +                mode = 3;
  +            else if (!strcmp(value, "by_name1"))
  +                mode = 4;
  +            else
  +                ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +            //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- 'mode' has to be 'by_id' or 'by_id1' or 'by_name' or 'by_name1'");
  +            
  +        }
  +        if (!strcmp(option, "type"))
  +        {
  +            if (strlen(value) != 4)
  +                ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +            //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- 'type' has to be four characters long");
  +            typeValid = 1;
  +            type = 0;
  +            type += value[0] << 24;
  +            type += value[1] << 16;
  +            type += value[2] << 8;
  +            type += value[3];
  +        }
  +        
  +        cmdStart = cmdEnd + 2;
  +        cmdEnd++;
  +    }
  +    
  +    if (mode == 0)
  +        ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +    //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Malformed resource locater requires a 'mode'");
  +    if (typeValid == 0)
  +        ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +    //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Malformed resource locater requires a 'type'");
  +    
  +    switch(mode)
  +    {
  +    case 1: case 2:
  +        id = atol(&resInfo[cmdEnd+1]);
  +        if (mode == 1)
  +            data = GetResource(type, id);
  +        else
  +            data = Get1Resource(type, id);
  +        break;
  +        
  +    case 3: case 4:
  +        if (strlen(&resInfo[cmdEnd]) >= 255)
  +            ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +        //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Resource names have to be 255 characters or less");
  +        strcpy((char*)name, &resInfo[cmdEnd]);
  +        name[0] = strlen((char*)&name[1]);
  +        if (mode == 3)
  +            data = GetNamedResource(type, name);
  +        else
  +            data = Get1NamedResource(type, name);
  +        break;
  +    }
  +    
  +    if (ResError() != noErr)
  +        ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +    //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Error opening resource");
  +    
  +    GetResInfo(data, &id, &type, name);
  +    len = GetResourceSizeOnDisk(data);
  +    if (ResError() != noErr)
  +        ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotOpenFile);
  +    //throw XMLPlatformUtilsException("XMLPlatformUtils::openFile -- Error loading resource info");
  +    
  +    valid = 1;
  + }
  +                                                
  + unsigned int XMLResFile::read(const unsigned int buffLen, XMLByte* const buff)
  + {
  +     unsigned int totAvail = len - pos;
  +     unsigned int numRead = (buffLen >= totAvail) ? totAvail : buffLen;
  +     
  +     HLock(data);
  +     memcpy(buff, *data, numRead);
  +     HUnlock(data);
  +     pos += numRead;
  +     return numRead;
  + }
  + 
  + void XMLResFile::close()
  + {
  +     if (!valid)
  +         ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotCloseFile);
  +     //throw XMLPlatformUtilsException("XMLPlatformUtils::curFilePos -- Not a valid file");
  +     ReleaseResource(data);
  +     valid = 0;
  + }
  + 
  + unsigned int XMLResFile::currPos()
  + {
  +     if (!valid)
  +         ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotGetCurPos);
  +     //throw XMLPlatformUtilsException("XMLPlatformUtils::curFilePos -- Not a valid file");
  +     return pos;
  + }
  + 
  + void XMLResFile::reset()
  + {
  +     if (!valid)
  +         ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotResetFile);
  +     //throw XMLPlatformUtilsException("XMLPlatformUtils::resetFile -- Not a valid file");
  +     pos = 0;
  + }
  + 
  + unsigned int XMLResFile::size()
  + {
  +     if (!valid)
  +         ThrowXML(XMLPlatformUtilsException, XML4CExcepts::File_CouldNotGetSize);
  +     //throw XMLPlatformUtilsException("XMLPlatformUtils::fileSize -- Not a valid file");
  +     return len;
  + }
  + 
  + XMLResFile::~XMLResFile()
  + {
  +     if (valid)
  +         close();
  + }
  +*/
  +
  +
   
  
  
  
  1.1                  xml-xerces/c/src/util/Platforms/MacOS/MacOSPlatformUtils.hpp
  
  Index: MacOSPlatformUtils.hpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   * 
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   * 
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   * 
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   * 
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache\@apache.org.
   * 
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   * 
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   * 
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /*
   * $Log: MacOSPlatformUtils.hpp,v $
   * Revision 1.1  2000/07/18 18:26:11  andyh
   * Mac OS update.
   * Contributed by James Berry <jb...@criticalpath.com>
   *
   */
   
  #pragma once
  
  #include <util/XercesDefs.hpp>
  #include <Files.h>
  
  class XMLMacAbstractFile
  {
      public:
          XMLMacAbstractFile() {}
          virtual ~XMLMacAbstractFile() {}
          
          virtual unsigned int currPos() = 0;
          virtual void close() = 0;
          virtual unsigned int size() = 0;
          virtual void open(const XMLCh* const) = 0;
          virtual unsigned int read(const unsigned int, XMLByte* const) = 0;
          virtual void reset() = 0;
  };
  
  
  class XMLMacFile : public XMLMacAbstractFile
  {
      public:
          XMLMacFile() : mFileRefNum(0), mFileValid(false) {}
          virtual ~XMLMacFile();
          
          unsigned int currPos();
          void close();
          unsigned int size();
          void open(const XMLCh* const);
          unsigned int read(const unsigned int, XMLByte* const);
          void reset();
          
      protected:
          short	mFileRefNum;
          bool	mFileValid;
          unsigned char pStr[300];
  };
  
  
  //	Convert fom FSRef/FSSpec to a Unicode character string path.
  //	Note that you'll need to delete [] that string after you're done with it!
  XMLCh*	XMLCreateFullPathFromRef(const FSRef& startingRef);
  XMLCh*	XMLCreateFullPathFromSpec(const FSSpec& startingSpec);
  
  //	Convert from path to FSRef/FSSpec
  bool	XMLParsePathToFSRef(const XMLCh* const pathName, FSRef& ref);
  bool	XMLParsePathToFSSpec(const XMLCh* const pathName, FSSpec& spec);
  
  
  
  
  /*		BROKEN LEGACY CODE UNLIKELY TO BE RESURRECTED
  #include <resources.h>
  
  class XMLResFile : public XMLMacAbstractFile
  {
      public:
          XMLResFile() : valid(0), type(0), id(0), pos(0), len(0) {}
          virtual ~XMLResFile();
          
          unsigned int currPos();
          void close();
          unsigned int size();
          void open(const char* const);
          unsigned int read(const unsigned int, XMLByte* const);
          void reset();
          
      protected:
          short valid;
          unsigned long type;
          short id;
          unsigned char name[300];
          Handle data;
          long pos;
          long len;
  };
  */
  
  
  
  1.1                  xml-xerces/c/src/util/Transcoders/MacOSUnicodeConverter/MacOSUnicodeConverter.cpp
  
  Index: MacOSUnicodeConverter.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   * 
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   * 
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   * 
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   * 
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache\@apache.org.
   * 
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   * 
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   * 
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /**
   * $Log: MacOSUnicodeConverter.cpp,v $
   * Revision 1.1  2000/07/18 18:26:15  andyh
   * Mac OS update.
   * Contributed by James Berry <jb...@criticalpath.com>
   *
   * Revision 1.8  2000/02/06 07:48:34  rahulj
   * Year 2K copyright swat.
   *
   * Revision 1.7  2000/01/25 23:14:19  roddey
   * Borland does not support wcsupr(), but does support _wcsupr(). Since VC++ does also,
   * _wcsupr() was used in order to have the both work with the same transcoding code.
   *
   * Revision 1.6  2000/01/25 22:49:58  roddey
   * Moved the supportsSrcOfs() method from the individual transcoder to the
   * transcoding service, where it should have been to begin with.
   *
   * Revision 1.5  2000/01/25 19:19:09  roddey
   * Simple addition of a getId() method to the xcode and netacess abstractions to
   * allow each impl to give back an id string.
   *
   * Revision 1.4  1999/12/18 00:22:33  roddey
   * Changes to support the new, completely orthagonal, transcoder architecture.
   *
   * Revision 1.3  1999/12/15 19:44:02  roddey
   * Now implements the new transcoding abstractions, with separate interface
   * classes for XML transcoders and local code page transcoders.
   *
   * Revision 1.2  1999/12/01 18:54:26  roddey
   * Small syntactical change to make it compile under Borland's compiler.
   * It does not make it worse under other compilers, so why not. Basically
   * it was just changing ::iswspace() to iswspace(), i.e. get rid of the ::
   * prefix, which freaked out Borland for some reason.
   *
   * Revision 1.1.1.1  1999/11/09 01:06:04  twl
   * Initial checkin
   *
   * Revision 1.2  1999/11/08 20:45:35  rahul
   * Swat for adding in Product name and CVS comment log variable.
   *
   */
  
  
  // ---------------------------------------------------------------------------
  //  Includes
  // ---------------------------------------------------------------------------
  #include <MacOSUnicodeConverter.hpp>
  #include <util/XMLUni.hpp>
  #include <util/XMLString.hpp>
  #include <util/TranscodingException.hpp>
  
  #if defined(XML_METROWERKS)
  #include <cwctype>
  #endif
  
  #include <cstddef>
  #include <cstring>
  
  #include <Errors.h>
  #include <Script.h>
  #include <TextUtils.h>
  #include <TextEncodingConverter.h>
  #include <TextCommon.h>
  #include <UnicodeConverter.h>
  #include <UnicodeUtilities.h>
  
  
  // ---------------------------------------------------------------------------
  //  Local, const data
  // ---------------------------------------------------------------------------
  static const XMLCh gMyServiceId[] =
  {
      chLatin_M, chLatin_a, chLatin_c, chLatin_O, chLatin_S, chNull
  };
  
  
  
  // ---------------------------------------------------------------------------
  //  MacOSUnicodeConverter: Constructors and Destructor
  // ---------------------------------------------------------------------------
  MacOSUnicodeConverter::MacOSUnicodeConverter()
  {
  }
  
  MacOSUnicodeConverter::~MacOSUnicodeConverter()
  {
  }
  
  
  // ---------------------------------------------------------------------------
  //  MacOSUnicodeConverter: The virtual transcoding service API
  // ---------------------------------------------------------------------------
  int MacOSUnicodeConverter::compareIString(  const XMLCh* const    comp1
                                            , const XMLCh* const    comp2)
  {
  #if 0
  	// We could use this if we have a reasonable c library
  	// metrowerks supports all of this.
  	// Note however that the c library version of towupper is probably
  	// not very good. The Unicode Utilities compare routine is probably
  	// more diligent, though surely not as quick.
  	const XMLCh* cptr1 = comp1;
  	const XMLCh* cptr2 = comp2;
  	
  	while ( (*cptr1 != 0) && (*cptr2 != 0) )
  	{
  	   wint_t wch1 = std::towupper(*cptr1);
  	   wint_t wch2 = std::towupper(*cptr2);
  	   if (wch1 != wch2)
  	       break;
  	   
  	   cptr1++;
  	   cptr2++;
  	}
  	return (int) ( std::towupper(*cptr1) - std::towupper(*cptr2) );
  #else
  	// Use the Unicode Utilities to do the compare
      UCCollateOptions collateOptions = 
                                kUCCollateComposeInsensitiveMask
                              | kUCCollateWidthInsensitiveMask
                              | kUCCollateCaseInsensitiveMask
                              | kUCCollatePunctuationSignificantMask
                              ;
                              
      Boolean equivalent = false;
      SInt32 order = 0;
      OSStatus status = UCCompareTextDefault(
                              collateOptions,	
                              reinterpret_cast<const UniChar* const>(comp1),
                              XMLString::stringLen(comp1),
                              reinterpret_cast<const UniChar* const>(comp2),
                              XMLString::stringLen(comp2),
                              &equivalent,
                              &order
                              );
                              
      return ((status != noErr) || equivalent) ? 0 : order;
  #endif
  }
  
  
  int MacOSUnicodeConverter::compareNIString( const   XMLCh* const    comp1
                                          , const XMLCh* const    comp2
                                          , const unsigned int    maxChars)
  {
  #if 0
  	// We could use this if we have a reasonable c library
  	// metrowerks supports all of this.
  	// Note however that the c library version of towupper is probably
  	// not very good. The Unicode Utilities compare routine is probably
  	// more diligent, though surely not as quick.
      unsigned int  n = 0;
      const XMLCh* cptr1 = comp1;
      const XMLCh* cptr2 = comp2;
  
      while ( (*cptr1 != 0) && (*cptr2 != 0) && (n < maxChars) )
      {
          wint_t wch1 = towupper(*cptr1);
          wint_t wch2 = towupper(*cptr2);
          if (wch1 != wch2)
              break;
          
          cptr1++;
          cptr2++;
          n++;
      }
      return (int) ( towupper(*cptr1) - towupper(*cptr2) );
  #else
  	// Use the Unicode Utilities to do the compare
      UCCollateOptions collateOptions = 
                                kUCCollateComposeInsensitiveMask
                              | kUCCollateWidthInsensitiveMask
                              | kUCCollateCaseInsensitiveMask
                              | kUCCollatePunctuationSignificantMask
                              ;
                              
  	std::size_t len1 = XMLString::stringLen(comp1);
  	std::size_t len2 = XMLString::stringLen(comp2);
  	
  	if (len1 > maxChars)
  		len1 = maxChars;
  		
  	if (len2 > maxChars)
  		len2 = maxChars;
                              
      Boolean equivalent = false;
      SInt32 order = 0;
      OSStatus status = UCCompareTextDefault(
                              collateOptions,	
                              reinterpret_cast<const UniChar* const>(comp1),
                              len1,
                              reinterpret_cast<const UniChar* const>(comp2),
                              len2,
                              &equivalent,
                              &order
                              );
                              
      return ((status != noErr) || equivalent) ? 0 : order;
  #endif
  }
  
  
  const XMLCh* MacOSUnicodeConverter::getId() const
  {
      return gMyServiceId;
  }
  
  
  bool MacOSUnicodeConverter::isSpace(const XMLCh toCheck) const
  {
  #if defined(XML_METROWERKS)
  	// Use this if there's a reasonable c library available.
  	// ProjectBuilder currently has no support for iswspace ;(
      return (std::iswspace(toCheck) != 0);
  #elif 0
  	// This is okay but probably kind of slow for what we need
      UCCharPropertyValue propValue = 0;
      
      OSStatus status = UCGetCharProperty(
                              reinterpret_cast<const UniChar*>(&toCheck),
                              1,					// size of toCheck in UniChars, right? Not bytes???
                              kUCCharPropTypeGenlCategory,
                              &propValue);
      return (status == noErr) && (propValue == kUCGenlCatSeparatorSpace);
  #elif defined(XML_MACOSX) || true
  	// This looks fairly good, assuming we're on an ascii compiler.
  	// We'll use this under ProjectBuilder for now.
  	return (toCheck == L' ');
  #endif
  }
  
  
  XMLLCPTranscoder* MacOSUnicodeConverter::makeNewLCPTranscoder()
  {
  	XMLLCPTranscoder* result = NULL;
  	OSStatus status = noErr;
  	TextToUnicodeInfo textToUnicodeInfo = NULL;
  	UnicodeToTextInfo unicodeToTextInfo = NULL;
  	
  	//	Get TextEncoding for current Mac System Script
  	TextEncoding systemTextEncoding;
  	status = UpgradeScriptInfoToTextEncoding (
  		smSystemScript, kTextLanguageDontCare, kTextRegionDontCare,
  		NULL, &systemTextEncoding);
  	
  	//	Try to create a Unicode converter from the system encoding to Unicode
  	if (status == noErr)
  		status = CreateTextToUnicodeInfoByEncoding(
  							systemTextEncoding,
  							&textToUnicodeInfo);
  							
  	//	Try to create a Unicode converter from Unicode to the system encoding
  	if (status == noErr)
  		status = CreateUnicodeToTextInfoByEncoding(
  							systemTextEncoding,
  							&unicodeToTextInfo);
  				
  	//	Clean up on error, else create our transcoder			
  	if (status != noErr)
  	{
  		if (textToUnicodeInfo != NULL)
  			DisposeTextToUnicodeInfo(&textToUnicodeInfo);
  			
  		if (unicodeToTextInfo != NULL)
  			DisposeUnicodeToTextInfo(&unicodeToTextInfo);
  	}
  	else
  		result = new MacOSLCPTranscoder(textToUnicodeInfo, unicodeToTextInfo);
  	
      return result;
  }
  
  
  bool MacOSUnicodeConverter::supportsSrcOfs() const
  {
  	// For now, we don't support source offsets
      return false;
  }
  
  
  void MacOSUnicodeConverter::upperCase(XMLCh* const toUpperCase) const
  {
  #if defined(XML_METROWERKS)
  	// Use this if there's a reasonable c library available.
  	// Metrowerks does this reasonably
  	wchar_t * p = (wchar_t*) toUpperCase;
  	wchar_t c;
  	
  	while ((c = *p) != 0)
  		*p++ = std::towupper(c);
  #elif 1
  	// This might work, assuming we're on an ascii compiler.
  	// We'll use this under ProjectBuilder for now.
  	// Note that this only handles the ascii portion of the
  	// string, leaving all other characters in original case.
  	wchar_t * p = (wchar_t*) toUpperCase;
  	wchar_t c;
  	
  	while ((c = *p) != 0)
  	{
  		if (c >= 'a' && c <= 'z')
  			c += 'A' - 'a';
  		*p++ = c;
  	}
  #elif 0
  	// This looks like it would work, but doesn't.
  	// Apart from CFString, there doesn't appear to be any
  	// other likely candidates for this support in the OS.
  	// Seems like the Unicode converter should have a routine
  	// do this!!!
      UppercaseText(reinterpret_cast<Ptr>(toUpperCase), XMLString::stringLen(toUpperCase), smUnicodeScript);
  #else
  	#error Sorry, no support for upperCase
  #endif
  }
  
  
  void
  MacOSUnicodeConverter::ConvertWideToNarrow(const XMLCh* wide, char* narrow, std::size_t maxChars)
  {
  	while (maxChars-- > 0)
  		if ((*narrow++ = *wide++) == 0)
  			break;
  }
  
  
  
  // ---------------------------------------------------------------------------
  //  MacOSTransService: The protected virtual transcoding service API
  // ---------------------------------------------------------------------------
  XMLTranscoder*
  MacOSUnicodeConverter::makeNewXMLTranscoder(const   XMLCh* const		encodingName
                                          ,       XMLTransService::Codes& resValue
                                          , const unsigned int			blockSize)
  {
  	XMLTranscoder* result = NULL;
  	resValue = XMLTransService::Ok;
  	
  	TextToUnicodeInfo textToUnicodeInfo = NULL;
  	UnicodeToTextInfo unicodeToTextInfo = NULL;
  
  	//	Map the encoding to a Mac OS Encoding value
  	TextEncoding textEncoding;
  	Str255 pasEncodingName;
  	char cEncodingName[256];
  	
  	// TODO: Use Transcode instead here!
  	ConvertWideToNarrow(encodingName, cEncodingName, sizeof(cEncodingName));
  	CopyCStringToPascal(cEncodingName, pasEncodingName);
  	
  	OSStatus status = TECGetTextEncodingFromInternetName (
  							&textEncoding,
  							pasEncodingName);
  							
  	//	Try to create a Unicode converter from the encoding to Unicode
  	if (status == noErr)
  		status = CreateTextToUnicodeInfoByEncoding(
  							textEncoding,
  							&textToUnicodeInfo);
  
  	//	Try to create a Unicode converter from Unicode to the encoding
  	if (status == noErr)
  		status = CreateUnicodeToTextInfoByEncoding(
  							textEncoding,
  							&unicodeToTextInfo);
  
  	//	Now create our own encoder, passing along the unicode converters.
  	if (status != noErr)
  	{
  		if (textToUnicodeInfo != NULL)
  			DisposeTextToUnicodeInfo(&textToUnicodeInfo);
  			
  		if (unicodeToTextInfo != NULL)
  			DisposeUnicodeToTextInfo(&unicodeToTextInfo);
  
  		resValue = XMLTransService::UnsupportedEncoding;
  	}
  	else
  		result = new MacOSTranscoder(encodingName, textToUnicodeInfo, unicodeToTextInfo, blockSize);
  	
      return result;
  }
  
  
  
  // ---------------------------------------------------------------------------
  //  MacOSTranscoder: Constructors and Destructor
  // ---------------------------------------------------------------------------
  MacOSTranscoder::MacOSTranscoder(const  XMLCh* const encodingName
  								, TextToUnicodeInfo	 textToUnicodeInfo
  								, UnicodeToTextInfo	 unicodeToTextInfo
                                  , const unsigned int blockSize) :
      XMLTranscoder(encodingName, blockSize),
      mTextToUnicodeInfo(textToUnicodeInfo),
      mUnicodeToTextInfo(unicodeToTextInfo)
  {
  }
  
  
  MacOSTranscoder::~MacOSTranscoder()
  {
  	//	Dispose our unicode converters
  	DisposeTextToUnicodeInfo(&mTextToUnicodeInfo);
  	DisposeUnicodeToTextInfo(&mUnicodeToTextInfo);
  }
  
  
  // ---------------------------------------------------------------------------
  //  MacOSTranscoder: The virtual transcoder API
  // ---------------------------------------------------------------------------
  
  unsigned int
  MacOSTranscoder::transcodeFrom(  const   XMLByte* const			srcData
                                  , const unsigned int			srcCount
                                  ,       XMLCh* const			toFill
                                  , const unsigned int			maxChars
                                  ,       unsigned int&			bytesEaten
                                  ,       unsigned char* const	charSizes)
  {
      ByteCount	bytesConsumed = 0;
      ByteCount	bytesProduced = 0;
      
      OSStatus status = ConvertFromTextToUnicode(
      	mTextToUnicodeInfo,
      	srcCount,
      	srcData,
      	kUnicodeUseFallbacksMask
  		// | kUnicodeKeepInfoMask
  		| kUnicodeDefaultDirectionMask
  		| kUnicodeLooseMappingsMask
  		// | kUnicodeStringUnterminatedMask
  		// | kUnicodeTextRunMask
  		,				// control flags
      	0,				// ioffset count
      	NULL,			// ioffset array
      	0,				// ooffset count
      	NULL,			// ooffset array
      	maxChars * sizeof(UniChar),
      	&bytesConsumed,
      	&bytesProduced,
      	reinterpret_cast<UniCharArrayPtr>(toFill));
      	
      if (status != noErr)
      {
          ThrowXML(TranscodingException, XMLExcepts::Trans_BadSrcSeq);
  
      	bytesConsumed = 0;
      	bytesProduced = 0;
      }
      	
      bytesEaten = bytesConsumed;
      return bytesProduced / sizeof(UniChar);
  }
  
  
  unsigned int
  MacOSTranscoder::transcodeTo(const  XMLCh* const    srcData
                              , const unsigned int    srcCount
                              ,       XMLByte* const  toFill
                              , const unsigned int    maxBytes
                              ,       unsigned int&   charsEaten
                              , const UnRepOpts       options)
  {
      ByteCount	bytesConsumed = 0;
      ByteCount	bytesProduced = 0;
      
  	OptionBits controlFlags =
  		  0
  		// | kUnicodeUseFallbacksMask
  		| kUnicodeLooseMappingsMask
  		// | kUnicodeKeepInfoMask
  		// | kUnicodeStringUnterminatedMask
  		;
  		
  	if (options == UnRep_RepChar)
  		controlFlags |= kUnicodeUseFallbacksMask;
  
      OSStatus status = ConvertFromUnicodeToText(
      	mUnicodeToTextInfo,
      	srcCount * sizeof(XMLCh),	// src byte count
      	reinterpret_cast<const UniChar*>(srcData),
      	controlFlags,		// control flags
      	0,					// ioffset count
      	NULL,				// ioffset array
      	0,					// ooffset count
      	NULL,				// ooffset array
      	maxBytes,
      	&bytesConsumed,
      	&bytesProduced,
      	toFill);
      	
      if (status != noErr)
      {
      	if (status == kTECUnmappableElementErr && options == UnRep_Throw)
      	{
      		XMLCh tmpBuf[16];
              XMLString::binToText((unsigned int)&srcData[bytesConsumed/sizeof(XMLCh)], tmpBuf, 16, 16);
              ThrowXML2
              (
                  TranscodingException
                  , XMLExcepts::Trans_Unrepresentable
                  , tmpBuf
                  , getEncodingName()
              );
      	}
      	
      	bytesConsumed = 0;
      	bytesProduced = 0;
      }
      	
      charsEaten = bytesConsumed / sizeof(XMLCh);
      return bytesProduced;
  }
  
  
  bool
  MacOSTranscoder::canTranscodeTo(const unsigned int toCheck) const
  {
      // We'll try just about anything...once!
      //
      // Actually, this is pretty heavilly cheating. If I knew
      // better what I was supposed to do...
      //
      // The windows code essentially tries to convert the character
      // with no surragates being used.
      //
      // TODO: clean this up.
      return true;
  }
  
  
  // ---------------------------------------------------------------------------
  //  MacOSLCPTranscoder: Constructors and Destructor
  // ---------------------------------------------------------------------------
  MacOSLCPTranscoder::MacOSLCPTranscoder(TextToUnicodeInfo textToUnicodeInfo, UnicodeToTextInfo unicodeToTextInfo)
   : mTextToUnicodeInfo(textToUnicodeInfo),
     mUnicodeToTextInfo(unicodeToTextInfo)
  {
  }
  
  
  MacOSLCPTranscoder::~MacOSLCPTranscoder()
  {
  	//	Dispose our unicode converters
  	DisposeTextToUnicodeInfo(&mTextToUnicodeInfo);
  	DisposeUnicodeToTextInfo(&mUnicodeToTextInfo);
  }
  
  
  // ---------------------------------------------------------------------------
  //  MacOSLCPTranscoder: Implementation of the virtual transcoder interface
  // ---------------------------------------------------------------------------
  
  // ---------------------------------------------------------------------------
  //	In order to implement calcRequiredSize we have to go ahead and do the
  //	conversion, which seems quite painful. The Mac Unicode converter has
  //	no way of saying "don't actually do the conversion." So we end up
  //	converting twic. It would be nice if the calling code could do some
  //	extra buffering to avoid this result.
  // ---------------------------------------------------------------------------
  unsigned int MacOSLCPTranscoder::calcRequiredSize(const char* const srcText)
  {
  	if (!srcText)
  		return 0;
  
  	const char* src = srcText;
  	std::size_t totalBytesProduced = 0;
  
  	OptionBits options =
  		  kUnicodeUseFallbacksMask
  		// | kUnicodeKeepInfoMask
  		| kUnicodeDefaultDirectionMask
  		| kUnicodeLooseMappingsMask
  		// | kUnicodeStringUnterminatedMask
  		// | kUnicodeTextRunMask
  		;
  
  	OSStatus status;
  	for (status = kTECOutputBufferFullStatus; status == kTECOutputBufferFullStatus; )
  	{
  	    ByteCount	bytesConsumed = 0;
  	    ByteCount	bytesProduced = 0;
  
  	    status = ConvertFromTextToUnicode(
  	    	mTextToUnicodeInfo,
  	    	std::strlen(src),	// src byte count
  	    	src,
  	    	options,			// control flags
  	    	0,					// ioffset count
  	    	NULL,				// ioffset array
  	    	0,					// ooffset count
  	    	NULL,				// ooffset array
  	    	kTempBufSize,
  	    	&bytesConsumed,
  	    	&bytesProduced,
  	    	(UniChar*)mTempBuf);
  
  		options |= kUnicodeKeepInfoMask;
  		
  		if (status == noErr || status == kTECOutputBufferFullStatus || status == kTECPartialCharErr)
  		{
  			totalBytesProduced	+= bytesProduced;
  			src	+= bytesConsumed;
  		}
  	}
  	
  	if (status != noErr && status != kTECPartialCharErr)
  		totalBytesProduced = 0;
  	
  	//	Return number of XMLCh characters required (not counting terminating NULL!)
  	return totalBytesProduced / sizeof(XMLCh);
  }
  
  
  // ---------------------------------------------------------------------------
  //	In order to implement calcRequiredSize we have to go ahead and do the
  //	conversion, which seems quite painful. The Mac Unicode converter has
  //	no way of saying "don't actually do the conversion." So we end up
  //	converting twic. It would be nice if the calling code could do some
  //	extra buffering to avoid this result.
  // ---------------------------------------------------------------------------
  unsigned int MacOSLCPTranscoder::calcRequiredSize(const XMLCh* const srcText)
  {
  	if (!srcText)
  		return 0;
  
  	const XMLCh* src = const_cast<const XMLCh*>(srcText);
  	std::size_t totalBytesProduced = 0;
  
  	OptionBits options =
  		  kUnicodeUseFallbacksMask
  		| kUnicodeLooseMappingsMask
  		// | kUnicodeKeepInfoMask
  		// | kUnicodeStringUnterminatedMask
  		;
  
  	OSStatus status;
  	for (status = kTECOutputBufferFullStatus; status == kTECOutputBufferFullStatus; )
  	{
  	    ByteCount	bytesConsumed = 0;
  	    ByteCount	bytesProduced = 0;
  
  	    status = ConvertFromUnicodeToText(
  	    	mUnicodeToTextInfo,
  	    	XMLString::stringLen(src) * sizeof(XMLCh),	// src byte count
  	    	reinterpret_cast<ConstUniCharArrayPtr>(src),
  	    	options,			// control flags
  	    	0,					// ioffset count
  	    	NULL,				// ioffset array
  	    	0,					// ooffset count
  	    	NULL,				// ooffset array
  	    	kTempBufSize,
  	    	&bytesConsumed,
  	    	&bytesProduced,
  	    	mTempBuf);
  
  		options |= kUnicodeKeepInfoMask;
  		
  		if (status == noErr || status == kTECOutputBufferFullStatus || status == kTECPartialCharErr)
  		{
  			totalBytesProduced	+= bytesProduced;
  			src	= reinterpret_cast<const XMLCh*>(reinterpret_cast<const char*>(src) + bytesConsumed);
  		}
  	}
  	
  	if (status != noErr && status != kTECPartialCharErr)
  		totalBytesProduced = 0;
  	
  	//	Return number of bytes required (not counting terminating NULL!)
  	return totalBytesProduced;
  }
  
  
  char* MacOSLCPTranscoder::transcode(const XMLCh* const srcText)
  {
  	if (!srcText)
  		return NULL;
  
  	char* result			= NULL;
  	const UniChar* src		= (const UniChar*)srcText;
  	std::size_t srcLen		= XMLString::stringLen(srcText) * sizeof(XMLCh);
  	std::size_t resultLen	= 0;
  
  	OptionBits options =
  		  kUnicodeUseFallbacksMask
  		| kUnicodeLooseMappingsMask
  		// | kUnicodeKeepInfoMask
  		// | kUnicodeStringUnterminatedMask
  		;
  
  	OSStatus status;
  	for (status = kTECOutputBufferFullStatus; status == kTECOutputBufferFullStatus; )
  	{
  		//	Convert an (internal) buffer full of text
  	    ByteCount	bytesConsumed = 0;
  	    ByteCount	bytesProduced = 0;
  
  	    status = ConvertFromUnicodeToText(
  	    	mUnicodeToTextInfo,
  	    	srcLen,				// src byte count
  	    	src,
  	    	options,			// control flags
  	    	0,					// ioffset count
  	    	NULL,				// ioffset array
  	    	0,					// ooffset count
  	    	NULL,				// ooffset array
  	    	kTempBufSize,
  	    	&bytesConsumed,
  	    	&bytesProduced,
  	    	mTempBuf);
  
  		options |= kUnicodeKeepInfoMask;
  		
  		//	Move the data to result buffer, reallocating as needed
  		if (status == noErr || status == kTECOutputBufferFullStatus || status == kTECPartialCharErr)
  		{
  			//	Allocate space for result
  			char* newResult = new char[resultLen + bytesProduced + 1];
  			if (newResult != NULL)
  			{
  				//	Incorporate previous result
  				if (result != NULL)
  				{
  					std::memcpy(newResult, result, resultLen);
  					delete [] result;
  				}
  				result = newResult;
  
  				//	Copy in new data
  				std::memcpy(result + resultLen, mTempBuf, bytesProduced);
  				resultLen += bytesProduced;
  				result[resultLen] = '\0';					
  			}
  			
  			src		= (const UniChar*)((const char*)src + bytesConsumed);
  			srcLen -= bytesConsumed;
  		}
  	}
  	
  	if (status != noErr && status != kTECPartialCharErr)
  	{
  		delete [] result;
  		result = NULL;
  	}
  	
  	return result;
  }
  
  
  XMLCh* MacOSLCPTranscoder::transcode(const char* const srcText)
  {
  	if (!srcText)
  		return NULL;
  
  	XMLCh* result			= NULL;
  	const char* src			= srcText;
  	std::size_t resultLen	= 0;
  	std::size_t srcLen		= std::strlen(src);
  
  	OptionBits options =
  		  kUnicodeUseFallbacksMask
  		// | kUnicodeKeepInfoMask
  		| kUnicodeDefaultDirectionMask
  		| kUnicodeLooseMappingsMask
  		// | kUnicodeStringUnterminatedMask
  		// | kUnicodeTextRunMask
  		;
  
  	OSStatus status;
  	for (status = kTECOutputBufferFullStatus; status == kTECOutputBufferFullStatus; )
  	{
  		//	Convert an (internal) buffer full of text
  	    ByteCount	bytesConsumed = 0;
  	    ByteCount	bytesProduced = 0;
  
  	    status = ConvertFromTextToUnicode(
  	    	mTextToUnicodeInfo,
  	    	srcLen,				// src byte count
  	    	src,
  	    	options,			// control flags
  	    	0,					// ioffset count
  	    	NULL,				// ioffset array
  	    	0,					// ooffset count
  	    	NULL,				// ooffset array
  	    	kTempBufSize,
  	    	&bytesConsumed,
  	    	&bytesProduced,
  	    	(UniChar*)mTempBuf);
  
  		options |= kUnicodeKeepInfoMask;
  		
  		//	Move the data to result buffer, reallocating as needed
  		if (status == noErr || status == kTECOutputBufferFullStatus || status == kTECPartialCharErr)
  		{
  			//	Allocate space for result
  			XMLCh* newResult = new XMLCh[(resultLen + bytesProduced) / sizeof(XMLCh) + 1];
  			if (newResult != NULL)
  			{
  				//	Incorporate previous result
  				if (result != NULL)
  				{
  					std::memcpy(newResult, result, resultLen);
  					delete [] result;
  				}
  				result = newResult;
  
  				//	Copy in new data
  				std::memcpy(result + resultLen, mTempBuf, bytesProduced);
  				resultLen += bytesProduced;
  				result[resultLen / sizeof(XMLCh)] = 0;					
  			}
  			
  			src		+= bytesConsumed;
  			srcLen  -= bytesConsumed;
  		}
  	}
  	
  	if (status != noErr && status != kTECPartialCharErr)
  	{
  		delete [] result;
  		result = NULL;
  	}
  	
  	return result;
  }
  
  
  bool MacOSLCPTranscoder::transcode( const   char* const     toTranscode
                                      ,       XMLCh* const    toFill
                                      , const unsigned int    maxChars)
  {
      // toFill must contain space for maxChars XMLCh characters + 1 (for terminating NULL).
  
      // Check for a couple of psycho corner cases
      if (!toTranscode || !maxChars)
      {
          toFill[0] = 0;
          return true;
      }
  
      if (!*toTranscode)
      {
          toFill[0] = 0;
          return true;
      }
  
      ByteCount	bytesConsumed = 0;
      ByteCount	bytesProduced = 0;
  
  	OptionBits options =
  		  kUnicodeUseFallbacksMask
  		// | kUnicodeKeepInfoMask
  		| kUnicodeDefaultDirectionMask
  		| kUnicodeLooseMappingsMask
  		// | kUnicodeStringUnterminatedMask
  		// | kUnicodeTextRunMask
  		;
  
      OSStatus status = ConvertFromTextToUnicode(
      	mTextToUnicodeInfo,
      	std::strlen(toTranscode),	// src byte count
      	toTranscode,
      	options,				// control flags
      	0,						// ioffset count
      	NULL,					// ioffset array
      	0,						// ooffset count
      	NULL,					// ooffset array
      	maxChars * sizeof(UniChar),
      	&bytesConsumed,
      	&bytesProduced,
      	reinterpret_cast<UniChar* const>(toFill));
      
      //	Zero terminate the output string
      std::size_t charsProduced = bytesProduced / sizeof(XMLCh);
      toFill[charsProduced] = L'\0';
  
  	return (status == noErr);
  }
  
  
      bool MacOSLCPTranscoder::transcode( const   XMLCh* const    toTranscode
                                      ,       char* const     toFill
                                      , const unsigned int    maxChars)
  {
      //	toFill must contain space for maxChars bytes characters + 1 (for terminating NULL).
  
      // Watch for a few psycho corner cases
      if (!toTranscode || !maxChars)
      {
          toFill[0] = 0;
          return true;
      }
  
      if (!*toTranscode)
      {
          toFill[0] = 0;
          return true;
      }
  
      ByteCount	bytesConsumed = 0;
      ByteCount	bytesProduced = 0;
  
  	OptionBits options =
  		  kUnicodeUseFallbacksMask
  		| kUnicodeLooseMappingsMask
  		// | kUnicodeKeepInfoMask
  		// | kUnicodeStringUnterminatedMask
  		;
  
      OSStatus status = ConvertFromUnicodeToText(
      	mUnicodeToTextInfo,
      	XMLString::stringLen(toTranscode) * sizeof(XMLCh),	// src byte count
      	reinterpret_cast<const UniChar*>(toTranscode),
      	options,				// control flags
      	0,						// ioffset count
      	NULL,					// ioffset array
      	0,						// ooffset count
      	NULL,					// ooffset array
      	maxChars,
      	&bytesConsumed,
      	&bytesProduced,
      	toFill);
      	
      //	Zero terminate the output string
      toFill[bytesProduced] = '\0';
  
  	return (status == noErr);
  }
  
  
  
  
  1.1                  xml-xerces/c/src/util/Transcoders/MacOSUnicodeConverter/MacOSUnicodeConverter.hpp
  
  Index: MacOSUnicodeConverter.hpp
  ===================================================================
  #ifndef MACOSUNICODECONVERTER_HPP
  #define MACOSUNICODECONVERTER_HPP
  
  /*
   * The Apache Software License, Version 1.1
   * 
   * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
   * reserved.
   * 
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   * 
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   * 
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   * 
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache\@apache.org.
   * 
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   * 
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   * 
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 1999, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /**
   * $Log: MacOSUnicodeConverter.hpp,v $
   * Revision 1.1  2000/07/18 18:26:16  andyh
   * Mac OS update.
   * Contributed by James Berry <jb...@criticalpath.com>
   *
   * Revision 1.6  2000/02/06 07:48:34  rahulj
   * Year 2K copyright swat.
   *
   * Revision 1.5  2000/01/25 22:49:58  roddey
   * Moved the supportsSrcOfs() method from the individual transcoder to the
   * transcoding service, where it should have been to begin with.
   *
   * Revision 1.4  2000/01/25 19:19:09  roddey
   * Simple addition of a getId() method to the xcode and netacess abstractions to
   * allow each impl to give back an id string.
   *
   * Revision 1.3  1999/12/18 00:22:33  roddey
   * Changes to support the new, completely orthagonal, transcoder architecture.
   *
   * Revision 1.2  1999/12/15 19:44:02  roddey
   * Now implements the new transcoding abstractions, with separate interface
   * classes for XML transcoders and local code page transcoders.
   *
   * Revision 1.1.1.1  1999/11/09 01:06:06  twl
   * Initial checkin
   *
   * Revision 1.2  1999/11/08 20:45:35  rahul
   * Swat for adding in Product name and CVS comment log variable.
   *
   */
  
  #include <util/TransService.hpp>
  #include <UnicodeConverter.h>
  #include <cstddef>
  
  //
  //  The transcoding service has to provide a couple of required string
  //  and character operations, but its most important service is the creation
  //  of transcoder objects. There are two types of transcoders, which are
  //  discussed below in the XMLTranscoder class' description.
  //
  class XMLUTIL_EXPORT MacOSUnicodeConverter : public XMLTransService
  {
  public :
      // -----------------------------------------------------------------------
      //  Public Constructors and Destructor
      // -----------------------------------------------------------------------
      ~MacOSUnicodeConverter();
  
      // -----------------------------------------------------------------------
      //  Implementation of the virtual transcoding service API
      // -----------------------------------------------------------------------
      virtual int compareIString
      (
          const   XMLCh* const    comp1
          , const XMLCh* const    comp2
      );
  
      virtual int compareNIString
      (
          const   XMLCh* const    comp1
          , const XMLCh* const    comp2
          , const unsigned int    maxChars
      );
  
      virtual const XMLCh* getId() const;
  
      virtual bool isSpace(const XMLCh toCheck) const;
  
      virtual XMLLCPTranscoder* makeNewLCPTranscoder();
  
      virtual bool supportsSrcOfs() const;
  
      virtual void upperCase(XMLCh* const toUpperCase) const;
  
  
  protected :
      // -----------------------------------------------------------------------
      //  Hidden constructors
      // -----------------------------------------------------------------------
      MacOSUnicodeConverter();
  
      // -----------------------------------------------------------------------
      //  Protected virtual methods
      // -----------------------------------------------------------------------
      virtual XMLTranscoder* makeNewXMLTranscoder
      (
          const   XMLCh* const            encodingName
          ,       XMLTransService::Codes& resValue
          , const unsigned int            blockSize
      );
  
  
  private :
  	friend class XMLPlatformUtils;
  	
      // -----------------------------------------------------------------------
      //  Unimplemented constructors and operators
      // -----------------------------------------------------------------------
      MacOSUnicodeConverter(const MacOSUnicodeConverter&);
      void operator=(const MacOSUnicodeConverter&);
      
      // -----------------------------------------------------------------------
      //  Private methods
      // -----------------------------------------------------------------------
  	void ConvertWideToNarrow(const XMLCh* wide, char* narrow, std::size_t maxChars);
  };
  
  
  //
  //  This type of transcoder is for non-local code page encodings, i.e.
  //  named encodings. These are used internally by the scanner to internalize
  //  raw XML into the internal Unicode format, and by writer classes to
  //  convert that internal Unicode format (which comes out of the parser)
  //  back out to a format that the receiving client code wants to use.
  //
  class XMLUTIL_EXPORT MacOSTranscoder : public XMLTranscoder
  {
  public :
      // -----------------------------------------------------------------------
      //  Constructors and Destructor
      // -----------------------------------------------------------------------
      MacOSTranscoder(
  	    const XMLCh* const		encodingName,
  	    TextToUnicodeInfo		textToUnicodeInfo,
  	    UnicodeToTextInfo		unicodeToTextInfo,
  	    const unsigned int		blockSize
  		);
      ~MacOSTranscoder();
  
  
      // -----------------------------------------------------------------------
      //  The virtual transcoding interface
      // -----------------------------------------------------------------------
      virtual unsigned int transcodeFrom
      (
          const   XMLByte* const          srcData
          , const unsigned int            srcCount
          ,       XMLCh* const            toFill
          , const unsigned int            maxChars
          ,       unsigned int&           bytesEaten
          ,       unsigned char* const    charSizes
      );
  
      virtual unsigned int transcodeTo
      (
          const   XMLCh* const    srcData
          , const unsigned int    srcCount
          ,       XMLByte* const  toFill
          , const unsigned int    maxBytes
          ,       unsigned int&   charsEaten
          , const UnRepOpts       options
      );
  
      virtual bool canTranscodeTo
      (
          const   unsigned int    toCheck
      )   const;
  
  
  
  
  private :
      // -----------------------------------------------------------------------
      //  Unimplemented constructors and operators
      // -----------------------------------------------------------------------
      MacOSTranscoder(const MacOSTranscoder&);
      void operator=(const MacOSTranscoder&);
      
      // -----------------------------------------------------------------------
      //  Private members
      // -----------------------------------------------------------------------
      TextToUnicodeInfo	mTextToUnicodeInfo;
      UnicodeToTextInfo	mUnicodeToTextInfo;
  };
  
  
  
  //
  //  This class is a specialized transcoder that only transcodes between
  //  the internal XMLCh format and the local code page. It is specialized
  //  for the very common job of translating data from the client app's
  //  native code page to the internal format and vice versa.
  //
  class XMLUTIL_EXPORT MacOSLCPTranscoder : public XMLLCPTranscoder
  {
  public :
      // -----------------------------------------------------------------------
      //  Constructors and Destructor
      // -----------------------------------------------------------------------
      MacOSLCPTranscoder(TextToUnicodeInfo textToUnicodeInfo, UnicodeToTextInfo unicodeToTextInfo);
      ~MacOSLCPTranscoder();
  
  
      // -----------------------------------------------------------------------
      //  The virtual transcoder API
      //
      //  NOTE:   All these APIs don't include null terminator characters in
      //          their parameters. So calcRequiredSize() returns the number
      //          of actual chars, not including the null. maxBytes and maxChars
      //          parameters refer to actual chars, not including the null so
      //          its assumed that the buffer is physically one char or byte
      //          larger.
      // -----------------------------------------------------------------------
      virtual unsigned int calcRequiredSize(const char* const srcText);
  
      virtual unsigned int calcRequiredSize(const XMLCh* const srcText);
  
      virtual char* transcode(const XMLCh* const toTranscode);
  
      virtual XMLCh* transcode(const char* const toTranscode);
  
      virtual bool transcode
      (
          const   char* const     toTranscode
          ,       XMLCh* const    toFill
          , const unsigned int    maxChars
      );
  
      virtual bool transcode
      (
          const   XMLCh* const    toTranscode
          ,       char* const     toFill
          , const unsigned int    maxChars
      );
  
  
  private :
      // -----------------------------------------------------------------------
      //  Unimplemented constructors and operators
      // -----------------------------------------------------------------------
      MacOSLCPTranscoder(const MacOSLCPTranscoder&);
      void operator=(const MacOSLCPTranscoder&);
      
      // -----------------------------------------------------------------------
      //  Private data members
      // -----------------------------------------------------------------------
      TextToUnicodeInfo	mTextToUnicodeInfo;
      UnicodeToTextInfo	mUnicodeToTextInfo;
      
      enum {
      	kTempBufSize	= 512
      };
      
      char mTempBuf[kTempBufSize];			// Temp buf used while in calcRequiredSize
  };
  
  #endif