2000-02-25 10:15:17 +00:00
|
|
|
// This may look like C code, but it is really -*- C++ -*-
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
// The Goldware Library
|
|
|
|
// Copyright (C) 1990-1999 Odinn Sorensen
|
|
|
|
// Copyright (C) 1999-2000 Alexander S. Aganichev
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Library General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Library General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Library General Public
|
|
|
|
// License along with this program; if not, write to the Free
|
|
|
|
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
|
|
// MA 02111-1307, USA
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
// $Id$
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
// File I/O class.
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <cerrno>
|
|
|
|
#include <cstdarg>
|
|
|
|
#include <gfile.h>
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
#if defined(_MSC_VER) /*&& (_MSC_VER >= 1400)*/
|
|
|
|
|
2006-04-26 17:06:23 +00:00
|
|
|
#define g_popen(comm, mode) _tpopen(comm, mode)
|
|
|
|
#define g_pclose(fp) _pclose(fp)
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
#define g_sopen(fn, of, sh, pm) _tsopen(fn, of, sh, pm)
|
|
|
|
#define g_close(fh) _close(fh)
|
|
|
|
#define g_read(fh, buf, cnt) _read(fh, buf, cnt)
|
|
|
|
#define g_write(fh, buf, cnt) _write(fh, buf, cnt)
|
|
|
|
#define g_tell(fh) _tell(fh)
|
|
|
|
#define g_lseek(fh, off, org) _lseek(fh, off, org)
|
|
|
|
#define g_filelength(fh) _filelength(fh)
|
|
|
|
#define g_chsize(fh, size) _chsize(fh, size)
|
|
|
|
|
|
|
|
#define g_fsopen(fn, of, sh) _tfsopen(fn, of, sh)
|
|
|
|
#define g_fdopen(fp, of) _tfdopen(fp, of)
|
|
|
|
#define g_fileno(fp) _fileno(fp)
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
2006-04-26 17:06:23 +00:00
|
|
|
#define g_popen(comm, mode) popen(comm, mode)
|
|
|
|
#define g_pclose(fp) pclose(fp)
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
#define g_sopen(fn, of, sh, pm) sopen(fn, of, sh, pm)
|
|
|
|
#define g_close(fh) close(fh)
|
|
|
|
#define g_read(fh, buf, cnt) read(fh, buf, cnt)
|
|
|
|
#define g_write(fh, buf, cnt) write(fh, buf, cnt)
|
|
|
|
#define g_tell(fh) tell(fh)
|
|
|
|
#define g_lseek(fh, off, org) lseek(fh, off, org)
|
|
|
|
#define g_filelength(fh) filelength(fh)
|
|
|
|
#define g_chsize(fh, size) chsize(fh, size)
|
|
|
|
|
|
|
|
#define g_fsopen(fn, of, sh) fsopen(fn, of, sh)
|
|
|
|
#define g_fdopen(fp, of) fdopen(fp, of)
|
|
|
|
#define g_fileno(fp) fileno(fp)
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define g_lock(fh, off, len) lock(fh, off, len)
|
|
|
|
#define g_unlock(fh, off, len) unlock(fh, off, len)
|
|
|
|
|
|
|
|
#define g_fclose(fp) fclose(fp)
|
|
|
|
#define g_fread(buf, rsz, cnt, fp) fread(buf, rsz, cnt, fp)
|
|
|
|
#define g_fwrite(buf, rsz, cnt, fp) fwrite(buf, rsz, cnt, fp)
|
|
|
|
#define g_fgetc(fp) fgetc(fp)
|
|
|
|
#define g_fputc(c, fp) fputc(c, fp)
|
|
|
|
#define g_fgets(str, cnt, fp) fgets(str, cnt, fp)
|
|
|
|
#define g_fputs(str, fp) fputs(str, fp)
|
|
|
|
#define g_fflush(fp) fflush(fp)
|
|
|
|
#define g_ftell(fp) ftell(fp)
|
2000-02-25 10:15:17 +00:00
|
|
|
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
// ------------------------------------------------------------------
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
gfile::gfile()
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
fh = -1;
|
|
|
|
fp = NULL;
|
|
|
|
status = EBADF;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
2006-04-26 17:06:23 +00:00
|
|
|
/*
|
2006-04-24 16:38:44 +00:00
|
|
|
gfile::gfile(int __fh)
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
fh = __fh;
|
|
|
|
fp = NULL;
|
|
|
|
status = 0;
|
|
|
|
}
|
2006-04-26 17:06:23 +00:00
|
|
|
*/
|
2000-02-25 10:15:17 +00:00
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
2006-04-26 17:06:23 +00:00
|
|
|
/*
|
2006-04-24 16:38:44 +00:00
|
|
|
gfile::gfile(FILE* __fp)
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
fh = -1;
|
|
|
|
fp = __fp;
|
|
|
|
status = 0;
|
|
|
|
}
|
2006-04-26 17:06:23 +00:00
|
|
|
*/
|
2000-02-25 10:15:17 +00:00
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
gfile::gfile(const char* __path, int __access, int __shflag, int __mode)
|
|
|
|
{
|
|
|
|
fh = -1;
|
|
|
|
fp = NULL;
|
|
|
|
Open(__path, __access, __shflag, __mode);
|
2000-02-25 10:15:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
gfile::gfile(const char* __path, const char* __mode, int __shflag)
|
|
|
|
{
|
|
|
|
fh = -1;
|
|
|
|
fp = NULL;
|
|
|
|
Fopen(__path, __mode, __shflag);
|
2000-02-25 10:15:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
gfile::~gfile()
|
|
|
|
{
|
|
|
|
if (fp != NULL) Fclose();
|
|
|
|
if (fh != -1) Close();
|
2000-02-25 10:15:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
bool gfile::isopen()
|
|
|
|
{
|
|
|
|
if ((fh != -1) or (fp != NULL)) return true;
|
2000-02-25 10:15:17 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::setfh(int __fh)
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
fh = __fh;
|
|
|
|
status = 0;
|
|
|
|
return fh;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
FILE* gfile::setfp(FILE* __fp)
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
fp = __fp;
|
|
|
|
status = 0;
|
|
|
|
return fp;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Open(const char* __path, int __access, int __shflag, int __mode)
|
|
|
|
{
|
|
|
|
#if defined(_tsopen_s)
|
|
|
|
status = _tsopen_s(&fh, __path, __access, __shflag, __mode);
|
|
|
|
return fh;
|
|
|
|
#else
|
|
|
|
fh = g_sopen(__path, __access, __shflag, __mode);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (fh == -1) ? errno : 0;
|
|
|
|
return fh;
|
2006-04-24 16:38:44 +00:00
|
|
|
#endif
|
2000-02-25 10:15:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Open(const char* __path, int __access, const char* __fmode, int __shflag, int __mode)
|
|
|
|
{
|
|
|
|
Open(__path, __access, __shflag, __mode);
|
|
|
|
Fdopen(__fmode);
|
2000-02-25 10:15:17 +00:00
|
|
|
return fh;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Close()
|
|
|
|
{
|
|
|
|
if (fp) return Fclose();
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int _ret = g_close(fh);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = _ret ? errno : 0;
|
|
|
|
fh = -1;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Read(void* __ptr, size_t __len)
|
|
|
|
{
|
|
|
|
int _ret = g_read(fh, __ptr, unsigned(__len));
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (_ret == -1) ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-05-14 01:19:58 +00:00
|
|
|
int gfile::Write(const void* __ptr, size_t __len)
|
2006-04-24 16:38:44 +00:00
|
|
|
{
|
|
|
|
int _ret = g_write(fh, __ptr, unsigned(__len));
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (_ret == -1) ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
long gfile::Tell()
|
|
|
|
{
|
|
|
|
long _ret = g_tell(fh);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (_ret == -1) ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
long gfile::Lseek(long __offset, int __direction)
|
|
|
|
{
|
|
|
|
long _ret = g_lseek(fh, __offset, __direction);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (_ret == -1) ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
long gfile::FileLength()
|
|
|
|
{
|
|
|
|
long _ret = g_filelength(fh);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (_ret == -1) ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::ChSize(long __size)
|
|
|
|
{
|
|
|
|
int _ret = g_chsize(fh, __size);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = _ret ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Lock(long __offset, long __len)
|
|
|
|
{
|
|
|
|
int _ret = g_lock(fh, __offset, __len);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = _ret ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Unlock(long __offset, long __len)
|
|
|
|
{
|
|
|
|
int _ret = g_unlock(fh, __offset, __len);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = _ret ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::GetFTime(time32_t *__ftime)
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
struct stat s;
|
2006-04-24 16:38:44 +00:00
|
|
|
if (fp) Fflush();
|
|
|
|
int rv = fstat(fh, &s);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (rv) ? errno : 0;
|
2006-04-24 16:38:44 +00:00
|
|
|
if (rv == 0) *__ftime = gfixstattime(time32_t(s.st_mtime));
|
|
|
|
else __ftime = 0;
|
2000-02-25 10:15:17 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
FILE* gfile::Fopen(const char* __path, const char* __mode, int __shflag)
|
|
|
|
{
|
|
|
|
fp = g_fsopen(__path, __mode, __shflag);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (fp == NULL) ? errno : 0;
|
2006-04-24 16:38:44 +00:00
|
|
|
if (fp) fh = g_fileno(fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
return fp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-26 17:06:23 +00:00
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
FILE* gfile::Popen(const char* __path, const char* __mode)
|
|
|
|
{
|
|
|
|
fp = g_popen(__path, __mode);
|
|
|
|
status = (fp == NULL) ? errno : 0;
|
|
|
|
if (fp) fh = g_fileno(fp);
|
|
|
|
return fp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
// ------------------------------------------------------------------
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
FILE* gfile::Fdopen(const char* __mode)
|
|
|
|
{
|
|
|
|
fp = g_fdopen(fh, __mode);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = fp ? 0 : errno;
|
2006-04-24 16:38:44 +00:00
|
|
|
if (fp) fh = g_fileno(fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
return fp;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
// ------------------------------------------------------------------
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Fclose()
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
int _ret = 0;
|
2006-04-24 16:38:44 +00:00
|
|
|
if (fp) _ret = g_fclose(fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = _ret ? errno : 0;
|
2006-04-24 16:38:44 +00:00
|
|
|
fp = NULL; fh = -1;
|
2000-02-25 10:15:17 +00:00
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
2006-04-26 17:06:23 +00:00
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
|
|
|
int gfile::Pclose()
|
|
|
|
{
|
|
|
|
int _ret = 0;
|
|
|
|
if (fp) _ret = g_pclose(fp);
|
|
|
|
status = _ret ? errno : 0;
|
|
|
|
fp = NULL; fh = -1;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
2000-02-25 10:15:17 +00:00
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
size_t gfile::Fread(void* __ptr, size_t __size, size_t __items)
|
|
|
|
{
|
|
|
|
size_t _ret = g_fread(__ptr, __size, __items, fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = ferror_() ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
// ------------------------------------------------------------------
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
size_t gfile::Fwrite(const void* __ptr, size_t __size, size_t __items)
|
|
|
|
{
|
|
|
|
size_t _ret = g_fwrite(__ptr, __size, __items, fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (_ret < __items) ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
// ------------------------------------------------------------------
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Fgetc()
|
|
|
|
{
|
|
|
|
int _ret = g_fgetc(fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = ferror_() ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
// ------------------------------------------------------------------
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Fputc(int __ch)
|
|
|
|
{
|
|
|
|
int _ret = g_fputc(__ch, fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = ferror_() ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
char* gfile::Fgets(char* __str, size_t __len)
|
|
|
|
{
|
|
|
|
char* _ret = g_fgets(__str, int(__len), fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (_ret == NULL) ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Fputs(const char* __str)
|
|
|
|
{
|
|
|
|
int _ret = g_fputs(__str, fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (_ret == EOF) ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
// ------------------------------------------------------------------
|
2000-02-25 10:15:17 +00:00
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Printf(const char* __format, ...)
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
va_list _argptr;
|
|
|
|
va_start(_argptr, __format);
|
2006-04-24 16:38:44 +00:00
|
|
|
int _outcount = vfprintf(fp, __format, _argptr);
|
2000-02-25 10:15:17 +00:00
|
|
|
va_end(_argptr);
|
|
|
|
return _outcount;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Fflush()
|
|
|
|
{
|
|
|
|
int _ret = g_fflush(fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = _ret ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
long gfile::Ftell()
|
|
|
|
{
|
|
|
|
long _ret = g_ftell(fp);
|
2000-02-25 10:15:17 +00:00
|
|
|
status = (_ret == -1) ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::Fseek(long __offset, int __direction)
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
int _ret = ::fseek(fp, __offset, __direction);
|
|
|
|
status = _ret ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|
|
|
|
|
2006-04-24 16:38:44 +00:00
|
|
|
int gfile::SetvBuf(char* __buf, int __type, size_t __size)
|
|
|
|
{
|
2000-02-25 10:15:17 +00:00
|
|
|
int _ret = ::setvbuf(fp, __buf, __type, __size);
|
|
|
|
status = _ret ? errno : 0;
|
|
|
|
return _ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------
|