--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/file.cpp Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,461 @@
+/************************************************************************
+ *
+ * file.cpp - definitions of testsuite file I/O helpers
+ *
+ * $Id: file.cpp 290020 2005-09-18 23:58:30Z sebor $
+ *
+ ************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
+ * Software division. Licensed under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0. Unless required by
+ * applicable law or agreed to in writing, software distributed under
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License
+ * for the specific language governing permissions and limitations under
+ * the License.
+ *
+ **************************************************************************/
+
+// expand _TEST_EXPORT macros
+#define _RWSTD_TEST_SRC
+#include <testdefs.h>
+#include <file.h>
+
+#if defined __linux__
+ // on Linux define _XOPEN_SOURCE to get CODESET defined in <langinfo.h>
+# define _XOPEN_SOURCE 500 /* Single Unix conformance */
+ // bring __int32_t into scope (otherwise <wctype.h> fails to compile)
+# include <sys/types.h>
+#endif // __linux__
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#if (!defined (_WIN32) && !defined (_WIN64)) || defined (__SYMBIAN32__)
+# include <langinfo.h> // for CODESET
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
+
+#include <assert.h> // for assert
+#include <errno.h> // for errno
+#include <locale.h> // for LC_XXX macros
+#include <stdio.h> // for sprintf, ...
+#include <stdlib.h> // for free, malloc, realloc
+#include <string.h> // for strcat, strcpy, strlen, ...
+#include <ctype.h>
+#include <wchar.h> // for wcslen, ...
+
+
+#ifndef PATH_MAX
+# define PATH_MAX 1024
+#endif
+
+#ifndef P_tmpdir
+# define P_tmpdir "/tmp/"
+#endif
+
+#ifndef _RWSTD_NO_PURE_C_HEADERS
+
+extern "C" int mkstemp (char*);
+
+#endif // _RWSTD_NO_PURE_C_HEADERS
+
+// write `str' using symbolic names from the Portable Character Set (PCS)
+// or using the <U00XX> notations for narrow characters outside that set
+// if (0 == str), writes out the CHARMAP section of the locale definition
+// file for the Portable Character Set (in POSIX-compliant format)
+_TEST_EXPORT void pcs_write (void *fpv, const char *str)
+{
+ FILE* const fp = _RWSTD_STATIC_CAST (FILE*, fpv);
+
+ // ASCII (ISO-646) character map definition
+ static const char* charmap[] = {
+ "<NUL>", "<SOH>", "<STX>", "<ETX>", "<EOT>", "<ENQ>", "<ACK>", "<BEL>",
+ "<backspace>",
+ "<tab>",
+ "<newline>",
+ "<vertical-tab>",
+ "<form-feed>",
+ "<carriage-return>",
+ "<SO>", "<SI>", "<DLE>", "<DC1>", "<DC2>", "<DC3>", "<DC4>", "<NAK>",
+ "<SYN>","<ETB>", "<CAN>", "<EM>", "<SUB>", "<ESC>", "<IS4>", "<IS3>",
+ "<IS2>", "<IS1>",
+ "<space>",
+ /* ! */ "<exclamation-mark>",
+ /* " */ "<quotation-mark>",
+ /* # */ "<number-sign>",
+ /* $ */ "<dollar-sign>",
+ /* % */ "<percent-sign>",
+ /* & */ "<ampersand>",
+ /* ' */ "<apostrophe>",
+ /* ( */ "<left-parenthesis>",
+ /* ) */ "<right-parenthesis>",
+ /* * */ "<asterisk>",
+ /* + */ "<plus-sign>",
+ /* , */ "<comma>",
+ /* - */ "<hyphen>",
+ /* . */ "<period>",
+ /* / */ "<slash>",
+ /* 0 */ "<zero>",
+ /* 1 */ "<one>",
+ /* 2 */ "<two>",
+ /* 3 */ "<three>",
+ /* 4 */ "<four>",
+ /* 5 */ "<five>",
+ /* 6 */ "<six>",
+ /* 7 */ "<seven>",
+ /* 8 */ "<eight>",
+ /* 9 */ "<nine>",
+ /* : */ "<colon>",
+ /* ; */ "<semicolon>",
+ /* < */ "<less-than-sign>",
+ /* = */ "<equals-sign>",
+ /* > */ "<greater-than-sign>",
+ /* ? */ "<question-mark>",
+ /* @ */ "<commercial-at>",
+ "<A>", "<B>", "<C>", "<D>", "<E>", "<F>", "<G>", "<H>", "<I>", "<J>",
+ "<K>", "<L>", "<M>", "<N>", "<O>", "<P>", "<Q>", "<R>", "<S>", "<T>",
+ "<U>", "<V>", "<W>", "<X>", "<Y>", "<Z>",
+ /* [ */ "<left-square-bracket>",
+ /* \ */ "<backslash>",
+ /* ] */ "<right-square-bracket>",
+ /* ^ */ "<circumflex>",
+ /* _ */ "<underscore>",
+ /* ` */ "<grave-accent>",
+ "<a>", "<b>", "<c>", "<d>", "<e>", "<f>", "<g>", "<h>", "<i>", "<j>",
+ "<k>", "<l>", "<m>", "<n>", "<o>", "<p>", "<q>", "<r>", "<s>", "<t>",
+ "<u>", "<v>", "<w>", "<x>", "<y>", "<z>",
+ /* { */ "<left-brace>",
+ /* | */ "<vertical-line>",
+ /* } */ "<right-brace>",
+ /* ~ */ "<tilde>",
+ "<DEL>"
+ };
+
+ if (str) {
+ // write out `str' using the charmap above
+ for (; *str; ++str) {
+ const unsigned char uc = _RWSTD_STATIC_CAST (unsigned char, *str);
+
+ if (uc < sizeof charmap / sizeof *charmap)
+ fprintf (fp, "%s", charmap [uc]);
+ else
+ fprintf (fp, "<U%04X>", uc);
+ }
+ }
+ else {
+
+#if !defined (_WIN32) && !defined (_WIN64)
+ const char* const codeset = nl_langinfo (CODESET);
+#else
+ // FIXME: determine the current code page
+ const char* const codeset = "UTF-8";
+#endif // _WIN{32,64}
+
+ fprintf (fp, "<code_set_name> \"%s\"\n", codeset);
+ fprintf (fp, "<mb_cur_max> 1\n");
+ fprintf (fp, "<mb_cur_min> 1\n");
+
+ fprintf (fp, "CHARMAP\n");
+
+ // write out the charmap above
+ for (unsigned i = 0; i != sizeof charmap / sizeof *charmap; ++i) {
+ fprintf (fp, "%s \\x%02x\n", charmap [i], i);
+ }
+
+ // write out duplicate symbolic names to prevent warnings
+ fprintf (fp, "<alert> \\x%02x\n", '\a');
+ fprintf (fp, "<hyphen-minus> \\x%02x\n", '-');
+ fprintf (fp, "<full-stop> \\x%02x\n", '.');
+ fprintf (fp, "<solidus> \\x%02x\n", '/');
+ fprintf (fp, "<reverse-solidus> \\x%02x\n", '\\');
+ fprintf (fp, "<circumflex-accent> \\x%02x\n", '^');
+ fprintf (fp, "<underline> \\x%02x\n", '_');
+ fprintf (fp, "<low-line> \\x%02x\n", '_');
+ fprintf (fp, "<left-curly-bracket> \\x%02x\n", '{');
+ fprintf (fp, "<right-curly-bracket> \\x%02x\n", '}');
+
+ fprintf (fp, "END CHARMAP\n");
+ }
+}
+
+
+_TEST_EXPORT
+const char* rw_tmpnam (char *buf)
+{
+#ifndef _RWSTD_NO_MKSTEMP
+# define TMP_TEMPLATE "tmpfile-XXXXXX"
+
+ if (!buf) {
+ static char fname_buf [sizeof (P_tmpdir) + sizeof (TMP_TEMPLATE)];
+
+ buf = fname_buf;
+ *buf = '\0';
+ }
+
+ if ('\0' == *buf) {
+ // copy the template to the buffer; make sure there is exactly
+ // one path separator character between P_tmpdir and the file
+ // name template (it doesn't really matter how many there are
+ // as long as it's at least one, but one looks better than two
+ // in diagnostic messages)
+ size_t len = sizeof (P_tmpdir) - 1;
+
+ memcpy (buf, P_tmpdir, len);
+ if (_RWSTD_PATH_SEP != buf [len - 1])
+ buf [len++] = _RWSTD_PATH_SEP;
+
+ memcpy (buf + len, TMP_TEMPLATE, sizeof TMP_TEMPLATE);
+ }
+
+ // prevent annoying glibc warnings (issued by the linker):
+ // the use of `tmpnam' is dangerous, better use `mkstemp'
+
+ const int fd = mkstemp (buf);
+
+ if (-1 == fd) {
+ fprintf (stderr, "%s:%d: mkstemp(\"%s\") failed: %s\n",
+ __FILE__, __LINE__, buf, strerror (errno));
+ return 0;
+ }
+
+ close (fd);
+
+ const char* const fname = buf;
+
+# undef TMP_TEMPLATE
+#else // if defined (_RWSTD_NO_MKSTEMP)
+
+# if defined (_WIN32) || defined (_WIN64)
+
+ // create a temporary file name
+ char* fname = tempnam (P_tmpdir, ".rwtest-tmp");
+
+ if (fname) {
+
+ static char tmpbuf [256];
+
+ if (0 == buf)
+ buf = tmpbuf;
+
+ _RWSTD_ASSERT (strlen (fname) < sizeof (tmpbuf));
+
+ // copy the generated temporary file name to the provided buffer
+ strcpy (buf, fname);
+
+ // free the storage allocated by tempnam()
+ free (fname);
+ fname = buf;
+ }
+ else {
+ fprintf (stderr, "%s:%d: tempnam(\"%s\", \"%s\") failed: %s\n",
+ __FILE__, __LINE__,
+ P_tmpdir, ".rwtest-tmp", strerror (errno));
+ }
+
+# else
+# if defined (__hpux) && defined (_RWSTD_REENTRANT)
+
+ // on HP-UX, in reentrant mode, tmpnam(0) fails by design
+
+ if (!buf) {
+ static char tmpbuf [L_tmpnam];
+ buf = tmpbuf;
+ *buf = '\0';
+ }
+
+# endif // __hpux && _REENTRANT
+
+ const char* const fname = tmpnam (buf);
+
+ if (!fname)
+ fprintf (stderr, "%s:%d: tmpnam(\"%s\") failed: %s\n",
+ __FILE__, __LINE__, buf, strerror (errno));
+
+# endif // _WIN{32,64}
+#endif // _RWSTD_NO_MKSTEMP
+
+ return fname;
+}
+
+
+_TEST_EXPORT
+size_t rw_fsize (const char *fname)
+{
+#ifdef __SYMBIAN32__
+
+ struct stat sb;
+
+ if (-1 == stat (fname, &sb))
+ return _RWSTD_SIZE_MAX;
+
+ return sb.st_size;
+#elif defined (_WIN32) || defined (_WIN64)
+
+ // note: both method of obtaining the size of a file
+ // just written by a process may fail (i.e., the size
+ // will be 0)
+
+# if 1
+
+ struct _stat sb;
+
+ if (-1 == _stat (fname, &sb))
+ return _RWSTD_SIZE_MAX;
+
+ return sb.st_size;
+
+# else
+
+ // #include <windows.h> for CreateFile() and GetFileSize()
+ const HANDLE hfile =
+ CreateFile (fname,
+ GENERIC_READ,
+ 0, // dwShareMode,
+ 0, // lpSecurityAttributes,
+ OPEN_EXISTING, // dwCreationDisposition,
+ FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes,
+ 0); // hTemplateFile
+
+ if (INVALID_HANDLE_VALUE == hfile)
+ return _RWSTD_SIZE_MAX;
+
+ const size_t size = GetFileSize (hfile, 0);
+
+ CloseHandle (hfile);
+
+ return size;
+
+# endif // 0/1
+
+#else // if !defined (_WIN{32,64})
+
+ struct stat sb;
+
+ if (stat (fname, &sb) == -1)
+ return _RWSTD_SIZE_MAX;
+
+ return sb.st_size;
+
+#endif // _WIN{32,64}
+
+}
+
+
+_TEST_EXPORT
+void* rw_fread (const char *fname,
+ size_t *size /* = 0 */,
+ const char *mode /* = "r" */)
+{
+ // buffer and size supplied by the user
+ static char* usrbuf = 0;
+ static size_t usrsize = 0;
+
+ // when called with 0 file name and non-0 size, set the static
+ // local buffer for the functions to use in subsequent calls
+ // with non-0 `fname' instead of dynamically allocating a new
+ // buffer
+ if (!fname && size) {
+
+ char* const oldbuf = usrbuf;
+
+ usrbuf = _RWSTD_CONST_CAST (char*, mode);
+ usrsize = usrbuf ? *size : 0;
+
+ return oldbuf;
+ }
+
+ static char buffer [1024];
+ static char* buf = usrbuf ? usrbuf : buffer;
+ static size_t bufsize = usrbuf ? usrsize : sizeof buffer;
+
+ // open the file in the specified mode
+ FILE* const fp = fopen (fname, mode);
+
+ if (!fp)
+ return 0;
+
+ for (char *bufend = buf; ; ) {
+ // compute the total number of bytes read from the file so far
+ // and the number of bytes that are still available in the buffer
+ const size_t bytes_read = size_t (bufend - buf);
+ const size_t bytes_avail = bufsize - bytes_read;
+
+ // try to read the contents of the file into the buffer
+ const size_t nbytes = fread (bufend, 1, bytes_avail, fp);
+
+ if (0 == nbytes) {
+ *bufend = '\0';
+
+ // store the number of bytes read
+ if (size)
+ *size = bytes_read;
+
+ break;
+ }
+
+ if (nbytes == bytes_avail) {
+
+ // do not grow user-specified buffer
+ if (buf == usrbuf)
+ break;
+
+ const size_t newsize = (bufsize + 1) * 2;
+
+ // increase the size of the buffer and continue reading
+ char *tmp = new char [newsize];
+ memcpy (tmp, buf, bufsize);
+
+ // deallocate buffer only if it's been
+ // previously dynamically allocated
+ if (buf != buffer)
+ delete[] buf;
+
+ bufsize = newsize;
+ bufend = tmp + bytes_read;
+ buf = tmp;
+ }
+
+ bufend += nbytes;
+ }
+
+ fclose (fp);
+
+ return buf;
+}
+
+
+_TEST_EXPORT
+size_t rw_fwrite (const char *fname,
+ const void *buf,
+ size_t size /* = -1 */,
+ const char *mode /* = "w" */)
+{
+ FILE *fp = 0;
+
+ if (buf)
+ fp = fopen (fname, mode);
+ else {
+ remove (fname);
+ return 0;
+ }
+
+ if (!fp)
+ return size_t (-1);
+
+ if (size_t (-1) == size)
+ size = strlen (_RWSTD_STATIC_CAST (const char*, buf));
+
+ // fwrite() returns the number of elements successfully written
+ // set it up so that the number of elements == the number of bytes
+ const size_t nbytes = fwrite (buf, 1 /* byte */, size, fp);
+
+ fclose (fp);
+
+ return nbytes;
+}