os/ossrv/stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/file.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/stdcpp/tsrc/Stdcpp_test/stdcxx/testengine/src/file.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,465 @@
     1.4 +/************************************************************************
     1.5 + *
     1.6 + * file.cpp - definitions of testsuite file I/O helpers
     1.7 + *
     1.8 + * $Id: file.cpp 290020 2005-09-18 23:58:30Z sebor $
     1.9 + *
    1.10 + ************************************************************************
    1.11 + *
    1.12 + * Copyright (c) 1994-2005 Quovadx,  Inc., acting through its  Rogue Wave
    1.13 + * Software division. Licensed under the Apache License, Version 2.0 (the
    1.14 + * "License");  you may  not use this file except  in compliance with the
    1.15 + * License.    You    may   obtain   a   copy   of    the   License    at
    1.16 + * http://www.apache.org/licenses/LICENSE-2.0.    Unless   required    by
    1.17 + * applicable law  or agreed to  in writing,  software  distributed under
    1.18 + * the License is distributed on an "AS IS" BASIS,  WITHOUT WARRANTIES OR
    1.19 + * CONDITIONS OF  ANY KIND, either  express or implied.  See  the License
    1.20 + * for the specific language governing permissions  and limitations under
    1.21 + * the License.
    1.22 + * 
    1.23 + **************************************************************************/
    1.24 +
    1.25 +// expand _TEST_EXPORT macros
    1.26 +#define _RWSTD_TEST_SRC
    1.27 +#include <testdefs.h>
    1.28 +#include <file.h>
    1.29 +
    1.30 +#if defined __linux__
    1.31 +   // on Linux define _XOPEN_SOURCE to get CODESET defined in <langinfo.h>
    1.32 +#  define _XOPEN_SOURCE   500   /* Single Unix conformance */
    1.33 +   // bring __int32_t into scope (otherwise <wctype.h> fails to compile)
    1.34 +#  include <sys/types.h>
    1.35 +#endif   // __linux__
    1.36 +
    1.37 +#include <fcntl.h>
    1.38 +#include <sys/stat.h>
    1.39 +
    1.40 +#if (!defined  (_WIN32) && !defined (_WIN64)) || defined (__SYMBIAN32__)
    1.41 +#  include <langinfo.h>   // for CODESET
    1.42 +#  include <unistd.h>
    1.43 +#else
    1.44 +#  include <io.h>
    1.45 +#endif
    1.46 +
    1.47 +#include <assert.h>   // for assert
    1.48 +#include <errno.h>    // for errno
    1.49 +#include <locale.h>   // for LC_XXX macros
    1.50 +#include <stdio.h>    // for sprintf, ...
    1.51 +#include <stdlib.h>   // for free, malloc, realloc
    1.52 +#include <string.h>   // for strcat, strcpy, strlen, ...
    1.53 +#include <ctype.h>
    1.54 +#include <wchar.h>    // for wcslen, ...
    1.55 +
    1.56 +
    1.57 +#ifndef PATH_MAX
    1.58 +#  define PATH_MAX   1024
    1.59 +#endif
    1.60 +
    1.61 +#ifndef P_tmpdir
    1.62 +#  define P_tmpdir "/tmp/"
    1.63 +#endif
    1.64 +
    1.65 +#ifndef _RWSTD_NO_PURE_C_HEADERS
    1.66 +
    1.67 +IMPORT_C int mkstemp (char*);
    1.68 +
    1.69 +#endif   // _RWSTD_NO_PURE_C_HEADERS
    1.70 +
    1.71 +// write `str' using symbolic names from the Portable Character Set (PCS)
    1.72 +// or using the <U00XX> notations for narrow characters outside that set
    1.73 +// if (0 == str), writes out the CHARMAP section of the locale definition
    1.74 +// file for the Portable Character Set (in POSIX-compliant format) 
    1.75 +_TEST_EXPORT void pcs_write (void *fpv, const char *str)
    1.76 +{
    1.77 +    FILE* const fp = _RWSTD_STATIC_CAST (FILE*, fpv);
    1.78 +
    1.79 +    // ASCII (ISO-646) character map definition
    1.80 +    static const char* charmap[] = {
    1.81 +        "<NUL>", "<SOH>", "<STX>", "<ETX>", "<EOT>", "<ENQ>", "<ACK>", "<BEL>",
    1.82 +        "<backspace>",
    1.83 +        "<tab>",
    1.84 +        "<newline>",
    1.85 +        "<vertical-tab>",
    1.86 +        "<form-feed>",
    1.87 +        "<carriage-return>",
    1.88 +        "<SO>", "<SI>", "<DLE>", "<DC1>", "<DC2>", "<DC3>", "<DC4>", "<NAK>",
    1.89 +        "<SYN>","<ETB>", "<CAN>", "<EM>", "<SUB>", "<ESC>", "<IS4>", "<IS3>",
    1.90 +        "<IS2>", "<IS1>",
    1.91 +        "<space>",
    1.92 +        /* ! */ "<exclamation-mark>",
    1.93 +        /* " */ "<quotation-mark>",
    1.94 +        /* # */ "<number-sign>",
    1.95 +        /* $ */ "<dollar-sign>",
    1.96 +        /* % */ "<percent-sign>",
    1.97 +        /* & */ "<ampersand>",
    1.98 +        /* ' */ "<apostrophe>",
    1.99 +        /* ( */ "<left-parenthesis>",
   1.100 +        /* ) */ "<right-parenthesis>",
   1.101 +        /* * */ "<asterisk>",
   1.102 +        /* + */ "<plus-sign>",
   1.103 +        /* , */ "<comma>",
   1.104 +        /* - */ "<hyphen>",
   1.105 +        /* . */ "<period>",
   1.106 +        /* / */ "<slash>",
   1.107 +        /* 0 */ "<zero>",
   1.108 +        /* 1 */ "<one>",
   1.109 +        /* 2 */ "<two>",
   1.110 +        /* 3 */ "<three>",
   1.111 +        /* 4 */ "<four>",
   1.112 +        /* 5 */ "<five>",
   1.113 +        /* 6 */ "<six>",
   1.114 +        /* 7 */ "<seven>",
   1.115 +        /* 8 */ "<eight>",
   1.116 +        /* 9 */ "<nine>",
   1.117 +        /* : */ "<colon>",
   1.118 +        /* ; */ "<semicolon>",
   1.119 +        /* < */ "<less-than-sign>",
   1.120 +        /* = */ "<equals-sign>",
   1.121 +        /* > */ "<greater-than-sign>",
   1.122 +        /* ? */ "<question-mark>",
   1.123 +        /* @ */ "<commercial-at>",
   1.124 +        "<A>", "<B>", "<C>", "<D>", "<E>", "<F>", "<G>", "<H>", "<I>", "<J>",
   1.125 +        "<K>", "<L>", "<M>", "<N>", "<O>", "<P>", "<Q>", "<R>", "<S>", "<T>",
   1.126 +        "<U>", "<V>", "<W>", "<X>", "<Y>", "<Z>",
   1.127 +        /* [ */ "<left-square-bracket>",
   1.128 +        /* \ */ "<backslash>",
   1.129 +        /* ] */ "<right-square-bracket>",
   1.130 +        /* ^ */ "<circumflex>",
   1.131 +        /* _ */ "<underscore>",
   1.132 +        /* ` */ "<grave-accent>",
   1.133 +        "<a>", "<b>", "<c>", "<d>", "<e>", "<f>", "<g>", "<h>", "<i>", "<j>",
   1.134 +        "<k>", "<l>", "<m>", "<n>", "<o>", "<p>", "<q>", "<r>", "<s>", "<t>",
   1.135 +        "<u>", "<v>", "<w>", "<x>", "<y>", "<z>",
   1.136 +        /* { */ "<left-brace>",
   1.137 +        /* | */ "<vertical-line>",
   1.138 +        /* } */ "<right-brace>",
   1.139 +        /* ~ */ "<tilde>",
   1.140 +        "<DEL>"
   1.141 +    };
   1.142 +
   1.143 +    if (str) {
   1.144 +        // write out `str' using the charmap above
   1.145 +        for (; *str; ++str) {
   1.146 +            const unsigned char uc = _RWSTD_STATIC_CAST (unsigned char, *str);
   1.147 +
   1.148 +            if (uc < sizeof charmap / sizeof *charmap)
   1.149 +                fprintf (fp, "%s", charmap [uc]);
   1.150 +            else
   1.151 +                fprintf (fp, "<U%04X>", uc);
   1.152 +        }
   1.153 +    }
   1.154 +    else {
   1.155 +
   1.156 +#if !defined (_WIN32) && !defined (_WIN64)
   1.157 +        const char* const codeset = nl_langinfo (CODESET);
   1.158 +#else
   1.159 +        // FIXME: determine the current code page
   1.160 +        const char* const codeset = "UTF-8";
   1.161 +#endif   // _WIN{32,64}
   1.162 +
   1.163 +        fprintf (fp, "<code_set_name> \"%s\"\n", codeset);
   1.164 +        fprintf (fp, "<mb_cur_max> 1\n");
   1.165 +        fprintf (fp, "<mb_cur_min> 1\n");
   1.166 +
   1.167 +        fprintf (fp, "CHARMAP\n");
   1.168 +
   1.169 +        // write out the charmap above
   1.170 +        for (unsigned i = 0; i != sizeof charmap / sizeof *charmap; ++i) {
   1.171 +            fprintf (fp, "%s \\x%02x\n", charmap [i], i);
   1.172 +        }
   1.173 +
   1.174 +        // write out duplicate symbolic names to prevent warnings
   1.175 +        fprintf (fp, "<alert> \\x%02x\n", '\a');
   1.176 +        fprintf (fp, "<hyphen-minus> \\x%02x\n", '-');
   1.177 +        fprintf (fp, "<full-stop> \\x%02x\n", '.');
   1.178 +        fprintf (fp, "<solidus> \\x%02x\n", '/');
   1.179 +        fprintf (fp, "<reverse-solidus> \\x%02x\n", '\\');
   1.180 +        fprintf (fp, "<circumflex-accent> \\x%02x\n", '^');
   1.181 +        fprintf (fp, "<underline> \\x%02x\n", '_');
   1.182 +        fprintf (fp, "<low-line> \\x%02x\n", '_');
   1.183 +        fprintf (fp, "<left-curly-bracket> \\x%02x\n", '{');
   1.184 +        fprintf (fp, "<right-curly-bracket> \\x%02x\n", '}');
   1.185 +
   1.186 +        fprintf (fp, "END CHARMAP\n");
   1.187 +    }
   1.188 +}
   1.189 +
   1.190 +
   1.191 +_TEST_EXPORT
   1.192 +const char* rw_tmpnam (char *buf)
   1.193 +{
   1.194 +#ifndef _RWSTD_NO_MKSTEMP
   1.195 +#  define TMP_TEMPLATE      "tmpfile-XXXXXX"
   1.196 +
   1.197 +    if (!buf) {
   1.198 +        static char fname_buf [sizeof (P_tmpdir) + sizeof (TMP_TEMPLATE)];
   1.199 +
   1.200 +        buf = fname_buf;
   1.201 +        *buf = '\0';
   1.202 +    }
   1.203 +
   1.204 +    if ('\0' == *buf) {
   1.205 +        // copy the template to the buffer; make sure there is exactly
   1.206 +        // one path separator character between P_tmpdir and the file
   1.207 +        // name template (it doesn't really matter how many there are
   1.208 +        // as long as it's at least one, but one looks better than two
   1.209 +        // in diagnostic messages)
   1.210 +        size_t len = sizeof (P_tmpdir) - 1;
   1.211 +
   1.212 +        memcpy (buf, P_tmpdir, len);
   1.213 +        if (_RWSTD_PATH_SEP != buf [len - 1])
   1.214 +            buf [len++] = _RWSTD_PATH_SEP;
   1.215 +
   1.216 +        memcpy (buf + len, TMP_TEMPLATE, sizeof TMP_TEMPLATE);
   1.217 +    }
   1.218 +
   1.219 +    // prevent annoying glibc warnings (issued by the linker):
   1.220 +    // the use of `tmpnam' is dangerous, better use `mkstemp'
   1.221 +
   1.222 +    const int fd = mkstemp (buf);
   1.223 +
   1.224 +    if (-1 == fd) {
   1.225 +        fprintf (stderr, "%s:%d: mkstemp(\"%s\") failed: %s\n",
   1.226 +                 __FILE__, __LINE__, buf, strerror (errno));
   1.227 +        return 0;
   1.228 +    }
   1.229 +
   1.230 +    close (fd);
   1.231 +
   1.232 +    const char* const fname = buf;
   1.233 +
   1.234 +#  undef TMP_TEMPLATE
   1.235 +#else   // if defined (_RWSTD_NO_MKSTEMP)
   1.236 +
   1.237 +#  if defined (_WIN32) || defined (_WIN64)
   1.238 +
   1.239 +    // create a temporary file name
   1.240 +    char* fname = tempnam (P_tmpdir, ".rwtest-tmp");
   1.241 +
   1.242 +    if (fname) {
   1.243 +
   1.244 +        static char tmpbuf [256];
   1.245 +
   1.246 +        if (0 == buf)
   1.247 +            buf = tmpbuf;
   1.248 +
   1.249 +        _RWSTD_ASSERT (strlen (fname) < sizeof (tmpbuf));
   1.250 +
   1.251 +        // copy the generated temporary file name to the provided buffer
   1.252 +        strcpy (buf, fname);
   1.253 +
   1.254 +        // free the storage allocated by tempnam()
   1.255 +        free (fname);
   1.256 +        fname = buf;
   1.257 +    }
   1.258 +    else {
   1.259 +        fprintf (stderr, "%s:%d: tempnam(\"%s\", \"%s\") failed: %s\n",
   1.260 +                 __FILE__, __LINE__,
   1.261 +                 P_tmpdir, ".rwtest-tmp", strerror (errno));
   1.262 +    }
   1.263 +
   1.264 +#  else
   1.265 +#    if defined (__hpux) && defined (_RWSTD_REENTRANT)
   1.266 +
   1.267 +    // on HP-UX, in reentrant mode, tmpnam(0) fails by design
   1.268 +
   1.269 +    if (!buf) {
   1.270 +        static char tmpbuf [L_tmpnam];
   1.271 +        buf = tmpbuf;
   1.272 +        *buf = '\0';
   1.273 +    }
   1.274 +
   1.275 +#    endif   // __hpux && _REENTRANT
   1.276 +
   1.277 +    const char* const fname = tmpnam (buf);
   1.278 +
   1.279 +    if (!fname)
   1.280 +        fprintf (stderr, "%s:%d: tmpnam(\"%s\") failed: %s\n",
   1.281 +                 __FILE__, __LINE__, buf, strerror (errno));
   1.282 +
   1.283 +#  endif   // _WIN{32,64}
   1.284 +#endif   // _RWSTD_NO_MKSTEMP
   1.285 +
   1.286 +    return fname;
   1.287 +}
   1.288 +
   1.289 +
   1.290 +_TEST_EXPORT
   1.291 +size_t rw_fsize (const char *fname)
   1.292 +{
   1.293 +#ifdef __SYMBIAN32__
   1.294 +
   1.295 +    struct stat sb;
   1.296 +    
   1.297 +    #ifdef __ARMCC__
   1.298 +    #pragma diag_suppress 63
   1.299 +    #endif
   1.300 +    if (-1 == stat (fname, &sb))
   1.301 +        return _RWSTD_SIZE_MAX;
   1.302 +       
   1.303 +
   1.304 +    return sb.st_size;
   1.305 +#elif defined (_WIN32) || defined (_WIN64)
   1.306 +
   1.307 +    // note: both method of obtaining the size of a file
   1.308 +    // just written by a process may fail (i.e., the size
   1.309 +    // will be 0)
   1.310 +
   1.311 +#  if 1
   1.312 +
   1.313 +    struct _stat sb;
   1.314 +
   1.315 +    if (-1 == _stat (fname, &sb))
   1.316 +        return _RWSTD_SIZE_MAX;
   1.317 +
   1.318 +    return sb.st_size;
   1.319 +
   1.320 +#  else
   1.321 +
   1.322 +    // #include <windows.h> for CreateFile() and GetFileSize()
   1.323 +    const HANDLE hfile =
   1.324 +        CreateFile (fname,
   1.325 +                    GENERIC_READ,
   1.326 +                    0,                     // dwShareMode,
   1.327 +                    0,                     // lpSecurityAttributes,
   1.328 +                    OPEN_EXISTING,         // dwCreationDisposition,
   1.329 +                    FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes,
   1.330 +                    0);                    // hTemplateFile
   1.331 +
   1.332 +    if (INVALID_HANDLE_VALUE == hfile)
   1.333 +        return _RWSTD_SIZE_MAX;
   1.334 +
   1.335 +    const size_t size = GetFileSize (hfile, 0);
   1.336 +
   1.337 +    CloseHandle (hfile);
   1.338 +
   1.339 +    return size;
   1.340 +
   1.341 +#  endif   // 0/1
   1.342 +
   1.343 +#else   // if !defined (_WIN{32,64})
   1.344 +
   1.345 +    struct stat sb;
   1.346 +
   1.347 +    if (stat (fname, &sb) == -1)
   1.348 +        return _RWSTD_SIZE_MAX;
   1.349 +
   1.350 +    return sb.st_size;
   1.351 +
   1.352 +#endif   // _WIN{32,64}
   1.353 +
   1.354 +}
   1.355 +
   1.356 +
   1.357 +_TEST_EXPORT
   1.358 +void* rw_fread (const char *fname,
   1.359 +                size_t     *size   /* = 0 */,
   1.360 +                const char *mode   /* = "r" */)
   1.361 +{
   1.362 +    // buffer and size supplied by the user
   1.363 +    static char*  usrbuf = 0;
   1.364 +    static size_t usrsize = 0;
   1.365 +
   1.366 +    // when called with 0 file name and non-0 size, set the static
   1.367 +    // local buffer for the functions to use in subsequent calls
   1.368 +    // with non-0 `fname' instead of dynamically allocating a new
   1.369 +    // buffer
   1.370 +    if (!fname && size) {
   1.371 +
   1.372 +        char* const oldbuf = usrbuf;
   1.373 +
   1.374 +        usrbuf  = _RWSTD_CONST_CAST (char*, mode);
   1.375 +        usrsize = usrbuf ? *size : 0;
   1.376 +
   1.377 +        return oldbuf;
   1.378 +    }
   1.379 +
   1.380 +    static char   buffer [1024];
   1.381 +    static char*  buf     = usrbuf ? usrbuf : buffer;
   1.382 +    static size_t bufsize = usrbuf ? usrsize : sizeof buffer;
   1.383 +
   1.384 +    // open the file in the specified mode
   1.385 +    FILE* const fp = fopen (fname, mode);
   1.386 +
   1.387 +    if (!fp)
   1.388 +        return 0;
   1.389 +
   1.390 +    for (char *bufend = buf; ; ) {
   1.391 +        // compute the total number of bytes read from the file so far
   1.392 +        // and the number of bytes that are still available in the buffer
   1.393 +        const size_t bytes_read  = size_t (bufend - buf);
   1.394 +        const size_t bytes_avail = bufsize - bytes_read;
   1.395 +
   1.396 +        // try to read the contents of the file into the buffer
   1.397 +        const size_t nbytes = fread (bufend, 1, bytes_avail, fp);
   1.398 +
   1.399 +        if (0 == nbytes) {
   1.400 +            *bufend = '\0';
   1.401 +
   1.402 +            // store the number of bytes read
   1.403 +            if (size)
   1.404 +                *size = bytes_read;
   1.405 +
   1.406 +            break;
   1.407 +        }
   1.408 +
   1.409 +        if (nbytes == bytes_avail) {
   1.410 +
   1.411 +            // do not grow user-specified buffer
   1.412 +            if (buf == usrbuf)
   1.413 +                break;
   1.414 +
   1.415 +            const size_t newsize = (bufsize + 1) * 2;
   1.416 +
   1.417 +            // increase the size of the buffer and continue reading
   1.418 +            char *tmp = new char [newsize];
   1.419 +            memcpy (tmp, buf, bufsize);
   1.420 +
   1.421 +            // deallocate buffer only if it's been
   1.422 +            // previously dynamically allocated
   1.423 +            if (buf != buffer)
   1.424 +                delete[] buf;
   1.425 +
   1.426 +            bufsize = newsize;
   1.427 +            bufend  = tmp + bytes_read;
   1.428 +            buf     = tmp;
   1.429 +        }
   1.430 +
   1.431 +        bufend += nbytes;
   1.432 +    }
   1.433 +
   1.434 +    fclose (fp);
   1.435 +
   1.436 +    return buf;
   1.437 +}
   1.438 +
   1.439 +
   1.440 +_TEST_EXPORT
   1.441 +size_t rw_fwrite (const char *fname,
   1.442 +                  const void *buf,
   1.443 +                  size_t      size /* = -1 */,
   1.444 +                  const char *mode /* = "w" */)
   1.445 +{
   1.446 +    FILE *fp = 0;
   1.447 +
   1.448 +    if (buf)
   1.449 +        fp = fopen (fname, mode);
   1.450 +    else {
   1.451 +        remove (fname);
   1.452 +        return 0;
   1.453 +    }
   1.454 +
   1.455 +    if (!fp)
   1.456 +        return size_t (-1);
   1.457 +
   1.458 +    if (size_t (-1) == size)
   1.459 +        size = strlen (_RWSTD_STATIC_CAST (const char*, buf));
   1.460 +
   1.461 +    // fwrite() returns the number of elements successfully written
   1.462 +    // set it up so that the number of elements == the number of bytes
   1.463 +    const size_t nbytes = fwrite (buf, 1 /* byte */, size, fp);
   1.464 +
   1.465 +    fclose (fp);
   1.466 +
   1.467 +    return nbytes;
   1.468 +}