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