7526 lines
275 KiB
C++
7526 lines
275 KiB
C++
|
||
|
||
#ifndef __ZCPPMAIIN__MAINHEAD_EX_H__
|
||
#define __ZCPPMAIIN__MAINHEAD_EX_H__
|
||
|
||
|
||
#ifndef _NO_USE_REEDDIR_R_
|
||
|
||
/* readdir_r() 함수가 실은 thread-safe 하지 않다고
|
||
해서 폐기되었다. -- 2025-09-07 14:55
|
||
*/
|
||
#define _NO_USE_REEDDIR_R_
|
||
|
||
#endif // !_NO_USE_REEDDIR_R_
|
||
|
||
|
||
#include<ctime>
|
||
#include<fstream>
|
||
#include<cstdio>
|
||
#include<cstdlib>
|
||
#include<string>
|
||
|
||
#include<sys/stat.h>
|
||
#include<sys/types.h>
|
||
#include<fcntl.h>
|
||
|
||
#include "ZCppMain/ZtCMainChars.H"
|
||
|
||
|
||
/* cf) #define OPEN_MAX 32 in <limit.h>
|
||
OPEN_MAX is max file numbers to open */
|
||
|
||
#ifdef __linux__
|
||
|
||
#include<unistd.h> // <unistd.h>(In Linux) == <direct.h> + <io.h> + ... (In Visual C++ 6.0)
|
||
#include<dirent.h>
|
||
#include<sys/time.h>
|
||
#include<sys/resource.h>
|
||
#include<sys/uio.h>
|
||
#include<aio.h>
|
||
|
||
#ifndef _T
|
||
#define _T(x) x
|
||
#endif
|
||
|
||
#elif defined(__sun__) // In Solaris
|
||
|
||
#include<unistd.h> // <unistd.h>(In Linux) == <direct.h> + <io.h> + ... (In Visual C++ 6.0)
|
||
#include<dirent.h>
|
||
#include<sys/time.h>
|
||
#include<sys/resource.h>
|
||
#include<sys/uio.h>
|
||
|
||
#ifndef _T
|
||
#define _T(x) x
|
||
#endif
|
||
|
||
#elif defined(_WIN)
|
||
|
||
#include<io.h>
|
||
#include<direct.h>
|
||
#include<windows.h> // for Win32 API
|
||
|
||
#ifndef _T
|
||
#define _T(x) TEXT(x)
|
||
#endif
|
||
|
||
#pragma comment(lib, "ws2_32") // ws2_32.lib 를 링크한다.
|
||
|
||
#else // 기본적으로 UNIX 계열이라고 간주한다.
|
||
|
||
#include<unistd.h> // <unistd.h>(In Linux) == <direct.h> + <io.h> + ... (In Visual C++ 6.0)
|
||
#include<dirent.h>
|
||
#include<sys/time.h>
|
||
#include<sys/resource.h>
|
||
#include<sys/uio.h>
|
||
|
||
#ifndef _T
|
||
#define _T(x) x
|
||
#endif
|
||
|
||
#endif
|
||
|
||
|
||
#ifndef _MAX_DIR
|
||
#define _MAX_DIR 512*2 // For unix.
|
||
#endif
|
||
|
||
|
||
using namespace std ;
|
||
using namespace ZNsMain;
|
||
|
||
|
||
/*/////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ char* ctime ( const time_t *timer );
|
||
wchar_t* _wctime( const time_t *timer );
|
||
|
||
Routine Required Header Compatibility
|
||
ctime <time.h> ANSI, Win 95, Win NT
|
||
_wctime <time.h> or <wchar.h> Win 95, Win NT
|
||
|
||
For additional compatibility information, see Compatibility in the Introduction.
|
||
|
||
Libraries
|
||
|
||
LIBC.LIB Single thread static library, retail version
|
||
LIBCMT.LIB Multithread static library, retail version
|
||
MSVCRT.LIB Import library for MSVCRT.DLL, retail version
|
||
|
||
Return Value
|
||
|
||
Each of these functions returns a pointer to the character string result.
|
||
If time represents a date before midnight, January 1, 1970, UTC, the function returns NULL.
|
||
|
||
|
||
■ time_t mktime( struct tm *timeptr ); ***
|
||
|
||
Routine Required Header Compatibility
|
||
mktime <time.h> ANSI, Win 95, Win NT
|
||
|
||
For additional compatibility information, see Compatibility in the Introduction.
|
||
|
||
Libraries
|
||
|
||
LIBC.LIB Single thread static library, retail version
|
||
LIBCMT.LIB Multithread static library, retail version
|
||
MSVCRT.LIB Import library for MSVCRT.DLL, retail version
|
||
|
||
Return Value
|
||
|
||
mktime returns the specified calendar time encoded as a value of type time_t.
|
||
If timeptr references a date before midnight, January 1, 1970,
|
||
or if the calendar time cannot be represented, the function returns ?1 cast to type time_t.
|
||
|
||
Remarks
|
||
|
||
The mktime function converts the supplied time structure (possibly incomplete)
|
||
pointed to by timeptr into a fully defined structure with normalized values
|
||
and then converts it to a time_t calendar time value.
|
||
For description of tm structure fields, see asctime.
|
||
The converted time has the same encoding as the values returned by the time function.
|
||
The original values of the tm_wday and tm_yday components of the timeptr structure are ignored,
|
||
and the original values of the other components are not restricted to their normal ranges.
|
||
|
||
mktime handles dates in any time zone
|
||
from midnight, January 1, 1970, to January 18, 19:14:07, 2038.
|
||
If successful, mktime sets the values of tm_wday and tm_yday as appropriate
|
||
and sets the other components to represent the specified calendar time,
|
||
but with their values forced to the normal ranges;
|
||
the final value of tm_mday is not set
|
||
until tm_mon and tm_year are determined.
|
||
When specifying a tm structure time,
|
||
set the tm_isdst field to 0 to indicate that standard time is in effect,
|
||
or to a value greater than 0 to indicate that daylight savings time is in effect,
|
||
or to a value less than zero to have the C run-time library code compute
|
||
whether standard time or daylight savings time is in effect.
|
||
(The C run-time library assumes the United States’s rules for implementing the calculation of Daylight Saving Time).
|
||
tm_isdst is a required field.
|
||
If not set, its value is undefined and the return value from mktime is unpredictable.
|
||
If timeptr points to a tm structure returned by a previous call to asctime, gmtime, or localtime,
|
||
the tm_isdst field contains the correct value.
|
||
|
||
Note that gmtime and localtime use a single statically allocated buffer for the conversion.
|
||
If you supply this buffer to mktime, the previous contents are destroyed.
|
||
|
||
struct tm
|
||
{
|
||
int tm_sec ; // seconds after the minute - [0,59]
|
||
int tm_min ; // minutes after the hour - [0,59]
|
||
int tm_hour ; // hours since midnight - [0,23]
|
||
int tm_mday ; // day of the month - [1,31]
|
||
int tm_mon ; // months since January - [0,11]
|
||
int tm_year ; // years since 1900
|
||
int tm_wday ; // days since Sunday - [0,6]
|
||
int tm_yday ; // days since January 1 - [0,365]
|
||
int tm_isdst; // daylight savings time flag
|
||
};
|
||
|
||
■ --
|
||
|
||
/////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
namespace ZNsMain
|
||
{
|
||
|
||
#if defined(_WIN)
|
||
|
||
/*////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ AI_SleepMiliSec 초 동안 잠든다. 1 mili 초를 지정하면 실제로 1 mili 초간 잠
|
||
드는 것이 아니라 약 16 mili 초 정도 잠든다. 이것은 10 mili 초를 지정하는 것
|
||
과 비슷하다(Window 2003, zeon 3.2, Ram 1G). 비슷한 사양의 리눅스에서 1 mili
|
||
초를 지정하면 약 4 mili 초 정도를 소요한다.
|
||
|
||
////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
inline void ZfSuspendExec(int AI_SleepMiliSec)
|
||
{
|
||
::Sleep(AI_SleepMiliSec);
|
||
}/*
|
||
inline void ZfSuspendExec(int AI_SleepMiliSec)*/
|
||
|
||
|
||
/*///////////////////////////////////////////////////
|
||
|
||
■ errno_t _putenv_s(
|
||
const char *name,
|
||
const char *value
|
||
);
|
||
|
||
errno_t _wputenv_s(
|
||
const wchar_t *name,
|
||
const wchar_t *value
|
||
);
|
||
|
||
※ int _putenv(const char*) 함수가 있는데 "변수명=변수값" 형태로 넘긴다.
|
||
|
||
이 함수보다 좀 더 안전한 함수가 _putenv_s() 이다.
|
||
|
||
※ The _putenv_s and _getenv_s families of functions are not thread-safe.
|
||
_getenv_s could return a string pointer
|
||
while _putenv_s is modifying the string, causing random failures.
|
||
Make sure that calls to these functions are synchronized.
|
||
|
||
_putenv_s 과 _getenv_s 류의 함수는 쓰레드에 안전하지 않다.
|
||
_putenv_s 과 _getenv_s 을 서로 다른 스레드에서 동시에 사용하는 경우
|
||
_getenv_s 는 수정중인 문자열 포인터를 반환할 수 있다.
|
||
|
||
///////////////////////////////////////////////////*/
|
||
|
||
inline bool ZfPutEnv(const char* APC_EnvName, const char* APC_Value)
|
||
{
|
||
#if __VISUAL_CPP_VER__>=200500
|
||
|
||
return ::_putenv_s(APC_EnvName, APC_Value)==0;
|
||
|
||
#else //__VISUAL_CPP_VER__<=200500
|
||
|
||
std::string VO_CStringEnv;
|
||
|
||
VO_CStringEnv+=APC_EnvName;
|
||
VO_CStringEnv+="=" ;
|
||
VO_CStringEnv+=APC_Value ;
|
||
|
||
return ::_putenv(VO_CStringEnv.data())==0;
|
||
|
||
#endif //__VISUAL_CPP_VER__<200500
|
||
}/*
|
||
inline bool ZfPutEnv(const char* APC_EnvName, const char* APC_Value)*/
|
||
|
||
inline bool ZfPutEnv(const char* APC_EnvData)
|
||
{
|
||
return ::_putenv(APC_EnvData)==0;
|
||
}/*
|
||
inline bool ZfPutEnv(const char* APC_EnvData)*/
|
||
|
||
inline long ZfWriteStdOut(LPCVOID APC_Buffer, DWORD ADW_BuffSize, LPOVERLAPPED AP_Overlapped=NULL)
|
||
{
|
||
// 표준 출력에 쓴다.
|
||
|
||
DWORD VDW_WrittenSize= 0 ;
|
||
|
||
const bool CB_IsOK = ////////////////////////////////////////
|
||
(
|
||
::WriteFile
|
||
(
|
||
::GetStdHandle(STD_OUTPUT_HANDLE), APC_Buffer
|
||
, ADW_BuffSize , &VDW_WrittenSize
|
||
, AP_Overlapped
|
||
)==TRUE
|
||
);
|
||
///////////////////////////////////////////////////////////////
|
||
|
||
if(CB_IsOK==false) return -1; return VDW_WrittenSize;
|
||
}/*
|
||
inline long ZfWriteStdOut(LPCVOID APC_Buffer, DWORD ADW_BuffSize, LPOVERLAPPED AP_Overlapped=NULL)*/
|
||
|
||
template<typename TString>
|
||
inline long ZfWriteStdOut(TString& AR_CStringOut, LPOVERLAPPED AP_Overlapped=NULL)
|
||
{
|
||
return ZfWriteStdOut(AR_CStringOut.c_str(), AR_CStringOut.size(), AP_Overlapped);
|
||
}/*
|
||
template<typename TString>
|
||
inline long ZfWriteStdOut(TString& AR_CStringOut, LPOVERLAPPED AP_Overlapped=NULL) */
|
||
|
||
inline long ZfReadStdIn(LPVOID AP_Buff, DWORD ADW_BuffSize, LPOVERLAPPED AP_Overlapped=NULL)
|
||
{
|
||
// 표준입력으로 부터 데이타를 읽는다.
|
||
// 에러이면 -1 을 그렇지 않으면 읽은 길이를 반환한다.
|
||
|
||
DWORD VDW_ReadCnt =0 ;
|
||
|
||
const bool CB_IsOK = /////////////////////////////////
|
||
(
|
||
::ReadFile
|
||
(
|
||
::GetStdHandle(STD_INPUT_HANDLE), AP_Buff,
|
||
ADW_BuffSize, &VDW_ReadCnt, AP_Overlapped
|
||
)==TRUE
|
||
);
|
||
//////////////////////////////////////////////////////
|
||
|
||
if(CB_IsOK==false) return -1; return VDW_ReadCnt;
|
||
}/*
|
||
inline long ZfReadStdIn(LPVOID AP_Buff, DWORD ADW_BuffSize, LPOVERLAPPED AP_Overlapped=NULL)*/
|
||
|
||
template<typename TString> long ZfReadStdIn(
|
||
TString& ARR_CStringRead, LPOVERLAPPED AP_Overlapped=NULL)
|
||
{
|
||
ZTycInt CI_StdBuffSize = 512 ;
|
||
|
||
if(ARR_CStringRead.size()<1)
|
||
ARR_CStringRead.resize(CI_StdBuffSize, ' ');
|
||
|
||
DWORD VDW_ReadCnt = 0 ;
|
||
|
||
const bool CB_IsOK = ///////////////////////
|
||
(
|
||
::ReadFile
|
||
(
|
||
::GetStdHandle(STD_INPUT_HANDLE)
|
||
, ARR_CStringRead.data()
|
||
, ARR_CStringRead.size()
|
||
, &VDW_ReadCnt, AP_Overlapped
|
||
)==TRUE
|
||
);
|
||
////////////////////////////////////////////
|
||
|
||
if(CB_IsOK==false)
|
||
{
|
||
ARR_CStringRead=""; return -1;
|
||
}/*
|
||
if(CB_IsOK==false)*/
|
||
|
||
ARR_CStringRead.resize(VDW_ReadCnt,' '); return VDW_ReadCnt;
|
||
}/*
|
||
template<typename TString> long ZfReadStdIn(
|
||
TString& ARR_CStringRead, LPOVERLAPPED AP_Overlapped=NULL) */
|
||
|
||
#else // !defined(_WIN)
|
||
|
||
/*/////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ std::SleepExec(int) 함수가 이미 glibc 확장에 있다.
|
||
|
||
■ ZfSuspendExec() 함수는 uslee() 함수를 이용하여 쉬는데, 쉬는 시간이 너무 크면
|
||
(1 초 이상이면)오류라는 뜻에서 음수를 반환하는 경우가 있다. '(주)인트라코어'의
|
||
취약점 진단 프로젝트를 하는데, KT 의 HP-UX(115.21.49.211) 가 그랬다.
|
||
uname -a 정보는
|
||
|
||
HP-UX sechpux B.11.11 U 9000/800 1106484218 unlimited-user license
|
||
|
||
gcc -v 정보는
|
||
|
||
Using built-in specs.
|
||
COLLECT_GCC=gcc
|
||
COLLECT_LTO_WRAPPER=/opt/hp-gcc-4.6.2/libexec/gcc/hppa1.1-hp-hpux11.11/4.6.2/lto-wrapper
|
||
Target: hppa1.1-hp-hpux11.11
|
||
Configured with: /tmp/gcc-4.6.2.tar.gz/gcc-4.6.2/configure --host=hppa1.1-hp-hpux11.11
|
||
--target=hppa1.1-hp-hpux11.11 --build=hppa1.1-hp-hpux11.11 --prefix=/opt/hp-gcc-4.6.2
|
||
--with-gnu-as --without-gnu-ld --enable-threads=posix --enable-languages=c,c++
|
||
--with-gmp=/proj/opensrc/be/hppa1.1-hp-hpux11.11
|
||
--with-mpfr=/proj/opensrc/be/hppa1.1-hp-hpux11.11 SED=/usr/bin/sed
|
||
Thread model: posix
|
||
gcc version 4.6.2 (GCC)
|
||
|
||
그래서 성공(0)을 반환하지 않으면, 500 밀리초 씩 쉬는 것으로 했다.
|
||
|
||
-- 2012-04-01 21:35:00
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
inline void ZfSuspendExec(int AI_SleepMiliSec)
|
||
{
|
||
if(::usleep(AI_SleepMiliSec*1000)==0) return;
|
||
|
||
int VI_SleepSec =AI_SleepMiliSec/1000 ;
|
||
int VI_ExtraMili=AI_SleepMiliSec%1000 ;
|
||
|
||
for(int i=0; i<VI_SleepSec; ++i)
|
||
{
|
||
// 1 초를 500 밀리초씩 2 번 나누어 쉰다.
|
||
|
||
::usleep(1000*500);
|
||
::usleep(1000*500);
|
||
}/*
|
||
for(int i=0; i<VI_SleepSec; ++i)*/
|
||
|
||
if(VI_ExtraMili>0) ::usleep(1000*VI_ExtraMili);
|
||
}/*
|
||
inline void ZfSuspendExec(int AI_SleepMiliSec)*/
|
||
|
||
|
||
/*///////////////////////////////////////////////////
|
||
|
||
■ setenv - 환경 변수를 바꾸거나 추가시킨다.
|
||
|
||
#include <stdlib.h>
|
||
|
||
int setenv(const char *name, const char *value, int overwrite);
|
||
void unsetenv(const char *name);
|
||
|
||
setenv() 함수는만일 name이 이미 존재하지 않는다면,
|
||
값 value를 가지고 있는 환경 변수 name을 추가시킨다.
|
||
만일 name가 환경 변수에 존재한다면, overwrite가 0 이 아니라면 그 값은 value로 바뀐다.
|
||
만일 overwrite가 0 이라면, name의 값은 바뀌지 않는다.
|
||
|
||
unsetenv() 함수는 환경 변수에서 변수 name 를 지운다.
|
||
setenv() 함수는 성공시 0 을 반환하거나,
|
||
만일 환경 변수에 공간이 충분하지 않다면 -1을 반환한다.
|
||
|
||
■ 미리 정의된 파일핸들 상수
|
||
|
||
0 : 표준입력 파일핸들
|
||
1 : 표준출력 파일핸들
|
||
2 : 표준에러 파일핸들
|
||
|
||
///////////////////////////////////////////////////*/
|
||
|
||
inline bool ZfPutEnv(const char* APC_EnvName, const char* APC_Value)
|
||
{
|
||
return ::setenv(APC_EnvName, APC_Value, 1)==0;
|
||
}/*
|
||
inline bool ZfPutEnv(const char* APC_EnvName, const char* APC_Value)*/
|
||
|
||
inline bool ZfPutEnv(const char* APC_EnvData) // "변수명=변수값"
|
||
{
|
||
return ::putenv(const_cast<char*>(APC_EnvData))==0;
|
||
}/*
|
||
inline bool ZfPutEnv(const char* APC_EnvData) // "변수명=변수값"*/
|
||
|
||
|
||
inline ssize_t ZfWriteStdOut(const void* APC_Buffer, ZTypLength AI_BuffSize)
|
||
{
|
||
return ::write(1, APC_Buffer, AI_BuffSize);
|
||
}/*
|
||
inline ssize_t ZfWriteStdOut(const void* APC_Buffer, ZTypLength AI_BuffSize)*/
|
||
|
||
template<typename TString>
|
||
inline ssize_t ZfWriteStdOut(TString& AR_CStringOut)
|
||
{
|
||
return ZfWriteStdOut(AR_CStringOut.c_str(), AR_CStringOut.size());
|
||
}/*
|
||
template<typename TString>
|
||
inline ssize_t ZfWriteStdOut(TString& AR_CStringOut) */
|
||
|
||
inline ssize_t ZfReadStdIn(void* AP_Buff, size_t AI_Count)
|
||
{
|
||
return ::read(0,AP_Buff,AI_Count);
|
||
}/*
|
||
inline ssize_t ZfReadStdIn(void* AP_Buff, size_t AI_Count)*/
|
||
|
||
template<typename TString> ssize_t ZfReadStdIn(TString& ARR_CStringRead)
|
||
{
|
||
ZTycInt CI_StdBuffSize=512;
|
||
|
||
if(ARR_CStringRead.size()<1)
|
||
ARR_CStringRead.resize(CI_StdBuffSize,' ');
|
||
|
||
ssize_t VI_ReadSize = ::read
|
||
( 0, ARR_CStringRead.c_str(), ARR_CStringRead.size() );
|
||
|
||
if(VI_ReadSize<=0)
|
||
{
|
||
ARR_CStringRead=""; return VI_ReadSize;
|
||
}/*
|
||
if(VI_ReadSize<=0)*/
|
||
|
||
ARR_CStringRead.resize(VI_ReadSize,' '); return VI_ReadSize;
|
||
}/*
|
||
template<typename TString> ssize_t ZfReadStdIn(TString& ARR_CStringRead) */
|
||
|
||
#endif // !defined(_WIN)
|
||
|
||
|
||
/*////////////////////////////////////////////////////////////////////////
|
||
|
||
■ ** IN time.h **
|
||
|
||
typedef struct tm
|
||
{
|
||
int tm_hour ; // hour (0 - 23)
|
||
int tm_isdst; // daylight saving time enabled/disabled
|
||
int tm_mday ; // day of month (1 - 31)
|
||
int tm_min ; // minutes (0 - 59)
|
||
int tm_mon ; // month (0 - 11 : 0 = January), 1 을 더한 값이 월이다.
|
||
int tm_sec ; // seconds (0 - 59)
|
||
int tm_wday ; // Day of week (0 - 6 : 0 = Sunday)
|
||
int tm_yday ; // Day of year (0 - 365), 1 을 더한 값이 그 해의 이 시점의 날수다.
|
||
int tm_year ; // Year less 1900, 1900 을 더한 값이 년도다.
|
||
}
|
||
|
||
■ ** timespec IN time.h **
|
||
|
||
SYNOPSIS
|
||
|
||
-- 아래 함수를 사용하면 Linux 에서도 초 단위보다 정밀한 시간을 구할 수 있다.
|
||
|
||
#include <time.h>
|
||
|
||
int clock_getres(clockid_t clk_id, struct timespec *res);
|
||
|
||
int clock_gettime(clockid_t clk_id, struct timespec *tp);
|
||
|
||
int clock_settime(clockid_t clk_id, const struct timespec *tp);
|
||
|
||
Link with -lrt.
|
||
|
||
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
|
||
|
||
clock_getres(), clock_gettime(), clock_settime(): _POSIX_C_SOURCE >= 199309L
|
||
|
||
DESCRIPTION
|
||
The function clock_getres() finds the resolution (precision) of the specified clock
|
||
clk_id, and, if res is non-NULL, stores it in the struct timespec pointed to by res.
|
||
The resolution of clocks depends on the implementation and cannot be configured by a
|
||
particular process. If the time value pointed to by the argument tp of clock_settime()
|
||
is not a multiple of res, then it is truncated to a multiple of res.
|
||
|
||
The functions clock_gettime() and clock_settime() retrieve and set the time of the
|
||
specified clock clk_id.
|
||
|
||
The res and tp arguments are timespec structures, as specified in <time.h>:
|
||
|
||
struct timespec {
|
||
time_t tv_sec ; // seconds
|
||
long tv_nsec; // nanoseconds
|
||
};
|
||
|
||
The clk_id argument is the identifier of the particular clock on which to act. A clock
|
||
may be system-wide and hence visible for all processes, or per-process if it measures
|
||
time only within a single process.
|
||
|
||
All implementations support the system-wide real-time clock, which is identified by
|
||
CLOCK_REALTIME. Its time represents seconds and nanoseconds since the Epoch. When its
|
||
time is changed, timers for a relative interval are unaffected, but timers for an abso-
|
||
lute point in time are affected.
|
||
|
||
More clocks may be implemented. The interpretation of the corresponding time values
|
||
and the effect on timers is unspecified.
|
||
|
||
Sufficiently recent versions of glibc and the Linux kernel support the following
|
||
clocks:
|
||
|
||
-- clk_id 은 아래 값 중 하나다 --
|
||
|
||
CLOCK_REALTIME
|
||
System-wide real-time clock. Setting this clock requires appropriate privi-
|
||
leges.
|
||
|
||
CLOCK_REALTIME_COARSE (since Linux 2.6.32; Linux-specific)
|
||
A faster but less precise version of CLOCK_REALTIME. Use when you need very
|
||
fast, but not fine-grained timestamps.
|
||
|
||
CLOCK_MONOTONIC
|
||
Clock that cannot be set and represents monotonic time since some unspecified
|
||
starting point.
|
||
|
||
CLOCK_MONOTONIC_COARSE (since Linux 2.6.32; Linux-specific)
|
||
A faster but less precise version of CLOCK_MONOTONIC. Use when you need very
|
||
fast, but not fine-grained timestamps.
|
||
|
||
CLOCK_MONOTONIC_RAW (since Linux 2.6.28; Linux-specific)
|
||
Similar to CLOCK_MONOTONIC, but provides access to a raw hardware-based time
|
||
that is not subject to NTP adjustments.
|
||
|
||
CLOCK_PROCESS_CPUTIME_ID
|
||
High-resolution per-process timer from the CPU.
|
||
|
||
CLOCK_THREAD_CPUTIME_ID
|
||
Thread-specific CPU-time clock.
|
||
|
||
RETURN VALUE
|
||
clock_gettime(), clock_settime() and clock_getres() return 0 for success, or -1 for
|
||
failure (in which case errno is set appropriately).
|
||
|
||
ERRORS
|
||
EFAULT tp points outside the accessible address space.
|
||
|
||
EINVAL The clk_id specified is not supported on this system.
|
||
|
||
EPERM clock_settime() does not have permission to set the clock indicated.
|
||
|
||
■ ** IN LINUX **
|
||
|
||
struct timeval
|
||
{
|
||
time_t tv_sec ; // seconds
|
||
suseconds_t tv_usec; // microseconds
|
||
};
|
||
|
||
struct timezone
|
||
{
|
||
int tz_minuteswest; // minutes W of Greenwich
|
||
int tz_dsttime; // type of dst correction
|
||
};
|
||
|
||
■ ** IN Window **
|
||
|
||
typedef struct _SYSTEMTIME
|
||
{
|
||
WORD wYear ;
|
||
WORD wMonth ;
|
||
WORD wDayOfWeek;
|
||
WORD wDay ;
|
||
WORD wHour ;
|
||
WORD wMinute;
|
||
WORD wSecond;
|
||
WORD wMilliseconds;
|
||
} SYSTEMTIME, *PSYSTEMTIME;
|
||
|
||
wYear
|
||
The year. The valid values for this member are 1601 through 30827.
|
||
wMonth
|
||
The month. This member can be one of the following values.Value Meaning
|
||
|
||
1 January
|
||
2 February
|
||
3 March
|
||
4 April
|
||
5 May
|
||
6 June
|
||
7 July
|
||
8 August
|
||
9 September
|
||
10 October
|
||
11 November
|
||
12 December
|
||
wDayOfWeek
|
||
|
||
The day of the week. This member can be one of the following values. Value Meaning
|
||
|
||
0 Sunday
|
||
1 Monday
|
||
2 Tuesday
|
||
3 Wednesday
|
||
4 Thursday
|
||
5 Friday
|
||
6 Saturday
|
||
|
||
wDay
|
||
The day of the month. The valid values for this member are 1 through 31.
|
||
wHour
|
||
The hour. The valid values for this member are 0 through 23.
|
||
wMinute
|
||
The minute. The valid values for this member are 0 through 59.
|
||
wSecond
|
||
The second. The valid values for this member are 0 through 59.
|
||
wMilliseconds
|
||
The millisecond. The valid values for this member are 0 through 999.
|
||
|
||
|
||
void GetSystemTime(LPSYSTEMTIME lpSystemTime);
|
||
|
||
■ time_t time ( time_t *timer);
|
||
__time32_t _time32(__time32_t *timer); // In Only Window
|
||
__time64_t _time64(__time64_t *timer); // In Only Window
|
||
|
||
Return the time as seconds elapsed since midnight, January 1, 1970. There is no error return.
|
||
|
||
1970 년 1월 1일 0시 이후 경과한 시간을 초로 나타낸다.
|
||
linux 64 bit 에서 time_t 는 8 바이트이다.
|
||
|
||
////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
/*////////////////////////////////////////////////////////////////////////
|
||
|
||
■ class ZCTime 에 시간을 더하거나 뺄 때에는, 더하거나 빼려는 시간을
|
||
초단위로 바꾼 후, 그 시간을 ZCTime::Plus() 와 Minus() 에 인수로 넘긴다.
|
||
|
||
////////////////////////////////////////////////////////////////////////*/
|
||
|
||
class ZCTime
|
||
{
|
||
public :
|
||
typedef time_t TypeIntTime;
|
||
private :
|
||
enum{ETimeBuffSize =30};
|
||
enum{ESecResolution=1 }; // 1 초를 이루는 값.
|
||
private :
|
||
char* mpc_TimeBuff;
|
||
protected:
|
||
struct tm mo_TimeObj;
|
||
time_t ml_TimeSec; // typedef long time_t;
|
||
bool mb_IsLocal;
|
||
private :
|
||
|
||
#if defined(_WIN) && defined(_REENTRANT)
|
||
|
||
static ZCMutexSmallInit& GetCMutexSmallInit()
|
||
{
|
||
static ZCMutexSmallInit SO_CMutexSmallInit; return SO_CMutexSmallInit;
|
||
}/*
|
||
static ZCMutexSmallInit& GetCMutexSmallInit()*/
|
||
|
||
#endif //defined(_WIN) && defined(_REENTRANT)
|
||
|
||
static bool SetLocalTimeObj(time_t AL_TimeSec, struct tm& ARR_StTime)
|
||
{
|
||
#ifdef _REENTRANT
|
||
#ifdef _WIN
|
||
ZNsMain::ZCMutexSmallLock VO_CMutexSmallLock(GetCMutexSmallInit());
|
||
|
||
struct tm* VP_StTime = ::localtime(&AL_TimeSec);
|
||
|
||
if(VP_StTime==0) return false;
|
||
|
||
ARR_StTime = *VP_StTime; return true;
|
||
#else
|
||
::localtime_r(&AL_TimeSec, &ARR_StTime); return true;
|
||
#endif
|
||
#else // !_REENTRANT
|
||
struct tm* VP_StTime = ::localtime(&AL_TimeSec);
|
||
|
||
if(VP_StTime==0) return false;
|
||
|
||
ARR_StTime = *VP_StTime; return true;
|
||
#endif // !_REENTRANT
|
||
}/*
|
||
static bool SetLocalTimeObj(time_t AL_TimeSec, struct tm& ARR_StTime)*/
|
||
|
||
bool SetLocalTimeObj()
|
||
{
|
||
return SetLocalTimeObj(ml_TimeSec, RR(mo_TimeObj));
|
||
}/*
|
||
bool SetLocalTimeObj()*/
|
||
|
||
static bool SetSystemTimeObj(time_t AL_TimeSec, struct tm& ARR_StTime)
|
||
{
|
||
#if defined(_REENTRANT)
|
||
#ifdef _WIN
|
||
ZNsMain::ZCMutexSmallLock
|
||
VO_CMutexSmallLock( GetCMutexSmallInit() );
|
||
|
||
struct tm* VP_StTime = ::gmtime(&AL_TimeSec);
|
||
|
||
if(VP_StTime==0) return false; //////
|
||
|
||
ARR_StTime = *VP_StTime; return true;
|
||
#else
|
||
::gmtime_r(&AL_TimeSec, &ARR_StTime); return true;
|
||
#endif
|
||
#else
|
||
struct tm* VP_StTime = ::gmtime(&AL_TimeSec);
|
||
|
||
if(VP_StTime==0) return false; //////
|
||
|
||
ARR_StTime = *VP_StTime; return true;
|
||
#endif
|
||
}/*
|
||
static bool SetSystemTimeObj(time_t AL_TimeSec, struct tm& ARR_StTime)*/
|
||
|
||
bool SetSystemTimeObj()
|
||
{
|
||
return SetSystemTimeObj(ml_TimeSec, RR(mo_TimeObj));
|
||
}/*
|
||
bool SetSystemTimeObj()*/
|
||
|
||
|
||
static bool SetTimeObj(time_t AL_TimeSec, struct tm& ARR_StTime, bool AB_IsLocalTime=true)
|
||
{
|
||
if(AB_IsLocalTime)
|
||
return SetLocalTimeObj (AL_TimeSec, RR(ARR_StTime));
|
||
else return SetSystemTimeObj(AL_TimeSec, RR(ARR_StTime));
|
||
}/*
|
||
static bool SetTimeObj(time_t AL_TimeSec, struct tm& ARR_StTime, bool AB_IsLocalTime=true)*/
|
||
|
||
bool SetTimeObj(bool AB_IsLocalTime)
|
||
{
|
||
return SetTimeObj(ml_TimeSec, RR(mo_TimeObj), AB_IsLocalTime);
|
||
}/*
|
||
bool SetTimeObj(bool AB_IsLocalTime)*/
|
||
|
||
bool SetTimeObj()
|
||
{
|
||
return SetTimeObj(mb_IsLocal);
|
||
}/*
|
||
bool SetTimeObj()*/
|
||
|
||
/*private:*/
|
||
public :
|
||
|
||
static TypeIntTime GetSecResolution()
|
||
{
|
||
return (TypeIntTime)ESecResolution;
|
||
}/*
|
||
static TypeIntTime GetSecResolution()*/
|
||
|
||
ZCTime(bool AB_IsLocalTime=true)
|
||
{
|
||
mb_IsLocal =AB_IsLocalTime;
|
||
mpc_TimeBuff=0; ::time(&ml_TimeSec);
|
||
|
||
::memset(&mo_TimeObj, 0, sizeof(::tm));
|
||
|
||
SetTimeObj(AB_IsLocalTime);
|
||
}/*
|
||
ZCTime(bool AB_IsLocalTime=true)*/
|
||
|
||
ZCTime(time_t AI_TimeVal, bool AB_IsLocalTime=true)
|
||
{
|
||
mpc_TimeBuff=0 ;
|
||
mb_IsLocal =AB_IsLocalTime;
|
||
ml_TimeSec =AI_TimeVal ;
|
||
|
||
::memset(&mo_TimeObj, 0, sizeof(::tm));
|
||
|
||
SetTimeObj(AB_IsLocalTime);
|
||
}/*
|
||
ZCTime(time_t AI_TimeVal, bool AB_IsLocalTime=true)*/
|
||
|
||
ZCTime(const ZCTime& rhs)
|
||
{
|
||
mpc_TimeBuff=0 ;
|
||
mb_IsLocal =rhs.mb_IsLocal;
|
||
ml_TimeSec =rhs.ml_TimeSec;
|
||
|
||
::memset(&mo_TimeObj,0,sizeof(::tm));
|
||
|
||
SetTimeObj(mb_IsLocal);
|
||
}/*
|
||
ZCTime(const ZCTime& rhs)*/
|
||
|
||
~ZCTime()
|
||
{
|
||
if(mpc_TimeBuff!=0) delete mpc_TimeBuff;
|
||
}/*
|
||
~ZCTime()*/
|
||
|
||
ZCTime& operator=(const ZCTime& rhs)
|
||
{
|
||
if(this==&rhs) return *this;
|
||
|
||
if(mpc_TimeBuff!=0)
|
||
{
|
||
delete mpc_TimeBuff; mpc_TimeBuff=0;
|
||
}/*
|
||
if(mpc_TimeBuff!=0)*/
|
||
|
||
mb_IsLocal=rhs.mb_IsLocal;
|
||
ml_TimeSec=rhs.ml_TimeSec;
|
||
|
||
SetTimeObj(mb_IsLocal); return *this;
|
||
}/*
|
||
ZCTime& operator=(const ZCTime& rhs)*/
|
||
|
||
|
||
bool InitTimeObj(bool AB_IsLocalTime)
|
||
{
|
||
::time(&ml_TimeSec); return SetTimeObj(AB_IsLocalTime);
|
||
}/*
|
||
bool InitTimeObj(bool AB_IsLocalTime)*/
|
||
|
||
bool InitTimeObj(time_t AI_TimeVal, bool AB_IsLocalTime)
|
||
{
|
||
ml_TimeSec=AI_TimeVal; return SetTimeObj(AB_IsLocalTime);
|
||
}/*
|
||
bool InitTimeObj(time_t AI_TimeVal, bool AB_IsLocalTime)*/
|
||
|
||
bool InitTimeObj()
|
||
{
|
||
return InitTimeObj(mb_IsLocal);
|
||
}/*
|
||
bool InitTimeObj()*/
|
||
|
||
bool InitTimeObj(time_t AI_TimeVal)
|
||
{
|
||
return InitTimeObj(AI_TimeVal, mb_IsLocal);
|
||
}/*
|
||
bool InitTimeObj(time_t AI_TimeVal)*/
|
||
|
||
|
||
bool InitLocalTimeObj (){return InitTimeObj(true );}
|
||
bool InitSystemTimeObj (){return InitTimeObj(false);}
|
||
bool InitTimeObjFromDate(
|
||
int AI_Year , int AI_Month, int AI_Day,
|
||
int AI_Hour=0, int AI_Min=0, int AI_Sec=0, int AI_MiliSec=0
|
||
/*//////////*/ )
|
||
{
|
||
ml_TimeSec = ZCTime::MakeTimeInt( /////////////
|
||
AI_Year, AI_Month, AI_Day,
|
||
AI_Hour, AI_Min , AI_Sec
|
||
/*/////////*/ ); //////////////////////////////
|
||
|
||
if(SetTimeObj(mb_IsLocal)==false) return false;
|
||
|
||
return AI_Year ==mo_TimeObj.tm_year+1900 &&
|
||
AI_Month==mo_TimeObj.tm_mon +1 &&
|
||
AI_Day ==mo_TimeObj.tm_mday &&
|
||
AI_Hour ==mo_TimeObj.tm_hour &&
|
||
AI_Min ==mo_TimeObj.tm_min &&
|
||
AI_Sec ==mo_TimeObj.tm_sec ;
|
||
///////
|
||
}/*
|
||
bool InitTimeObjFromDate(
|
||
int AI_Year , int AI_Month, int AI_Day,
|
||
int AI_Hour=0, int AI_Min=0, int AI_Sec=0, int AI_MiliSec=0
|
||
////////////// ) */
|
||
|
||
|
||
tm& GetTimeObj()
|
||
{
|
||
return mo_TimeObj;
|
||
}/*
|
||
tm& GetTimeObj()*/
|
||
|
||
|
||
inline TypeIntTime GetTimeSec() const{return ml_TimeSec;}
|
||
inline TypeIntTime GetTimeInt() const{return ml_TimeSec;} // for compatibility with linux
|
||
|
||
inline TypeIntTime AddTimeIntMilli(TypeIntTime AI_AddMilli) const
|
||
{ return ml_TimeSec + (AI_AddMilli/1000) ; }
|
||
inline TypeIntTime AddTimeIntSec (TypeIntTime AI_AddSec ) const
|
||
{ return ml_TimeSec + AI_AddSec ; }
|
||
|
||
inline TypeIntTime AddTimeIntMilliRev(TypeIntTime AI_AddMilli) const
|
||
{
|
||
// ESecResolution/1000 < 1 인 경우에는 1 milli 초를 표현할 수 없으니까,
|
||
// ESecResolution/1000 이상이면서 가장 가까운 배수로 보정(revise)하는
|
||
// 것이다. 스케줄러에서 예약 시간을 등록할 때 필요하다.
|
||
// 근데 ESecResolution/1000 < 1 인 경우가 없게 ZCStdTime 클래스를 만들어
|
||
// 서 AddTimeIntMilliRev() 이 필요없게 되었다. -- 2018-06-25 14:06:00
|
||
|
||
if(GetSecResolution()/1000 >= 1) return AddTimeIntMilli(AI_AddMilli);
|
||
|
||
// AI_AddMilli>=0 이면서 가장 가까운 1000 의 배수에 맞춘다.
|
||
|
||
TypeIntTime VI_Revised =
|
||
(AI_AddMilli/1000)*1000 + ( (AI_AddMilli%1000)>0 ? 1000 :0 ) ;
|
||
|
||
AddTimeIntMilli(VI_Revised);
|
||
}/*
|
||
inline TypeIntTime AddTimeIntMilliRev(TypeIntTime AI_AddMilli) const*/
|
||
|
||
inline TypeIntTime AddTimeIntSecRev(TypeIntTime AI_AddSec) const
|
||
{
|
||
// ESecResolution < 1 인 경우에는 1 초를 표현할 수 없으니까,
|
||
// ESecResolution 이상이면서 가장 가까운 배수로 보정(revise)하는
|
||
// 것이다. 스케줄러에서 예약 시간을 등록할 때 필요하다.
|
||
|
||
return AddTimeIntSec(AI_AddSec); // 특별한 처리가 필요없다.
|
||
}/*
|
||
inline TypeIntTime AddTimeIntSecRev(TypeIntTime AI_AddSec) const*/
|
||
|
||
|
||
inline time_t MakeTimeInt()
|
||
{
|
||
return ::mktime(&mo_TimeObj);
|
||
|
||
/*////////////////////////////////////////////////////////////
|
||
|
||
■ Get a integer that is information about day, hour, sec etc
|
||
from struct tm pointer mp_TimeObj
|
||
|
||
■ mktime() 은 에러의 경우 -1 을 반환한다.
|
||
|
||
////////////////////////////////////////////////////////////*/
|
||
}/*
|
||
inline time_t MakeTimeInt()*/
|
||
|
||
static inline time_t MakeTimeInt(struct tm& AR_TimeStruct)
|
||
{
|
||
return ::mktime(&AR_TimeStruct);
|
||
}/*
|
||
static inline time_t MakeTimeInt(struct tm& AR_TimeStruct)*/
|
||
|
||
static inline time_t MakeTimeInt(int AI_Year, int AI_Month, int AI_Day, int AI_Hour=0, int AI_Min=0, int AI_Sec=0)
|
||
{
|
||
::tm VO_TimeStr; ::memset(&VO_TimeStr, 0, sizeof(::tm));
|
||
|
||
VO_TimeStr.tm_year=AI_Year-1900 ;
|
||
VO_TimeStr.tm_mon =AI_Month-1 ;
|
||
VO_TimeStr.tm_mday=AI_Day ;
|
||
VO_TimeStr.tm_hour=AI_Hour ;
|
||
VO_TimeStr.tm_min =AI_Min ;
|
||
VO_TimeStr.tm_sec =AI_Sec ;
|
||
|
||
return ::mktime(&VO_TimeStr);
|
||
|
||
/*///////////////////////////////////////////////////////////////////
|
||
|
||
■ MakeTimeInt(2010,2,32) 을 호출하면(2010 년 2월 32 일자로 호출하면)
|
||
2010-03-04 00:00:00 에 해당하는 time_t 를 리턴한다. 따라서 이 함수
|
||
를 호출할 때 정확한 인수를 주는 것이 제일 좋지만, 차선책으로 인수가
|
||
지정하는 날짜와 이 함수가 리턴한 time_t 에 대한 날짜를 비교해 보는
|
||
것도 좋을 것 같다.
|
||
|
||
-- 2010-03-01 18:21;00
|
||
|
||
///////////////////////////////////////////////////////////////////*/
|
||
}/*
|
||
static inline time_t MakeTimeInt(int AI_Year, int AI_Month, int AI_Day, int AI_Hour=0, int AI_Min=0, int AI_Sec=0)*/
|
||
|
||
static bool IsValidTime(time_t AI_Time, int AI_Year, int AI_Month, int AI_Day, int AI_Hour, int AI_Min, int AI_Sec, bool AB_IsLocalTime=true)
|
||
{
|
||
struct ::tm VO_TimeStr; const bool CB_IsOK =
|
||
SetTimeObj(AI_Time, VO_TimeStr, AB_IsLocalTime);
|
||
|
||
if(CB_IsOK==false) return false;
|
||
|
||
return AI_Year ==VO_TimeStr.tm_year+1900 &&
|
||
AI_Month==VO_TimeStr.tm_mon +1 &&
|
||
AI_Day ==VO_TimeStr.tm_mday &&
|
||
AI_Hour ==VO_TimeStr.tm_hour &&
|
||
AI_Min ==VO_TimeStr.tm_min &&
|
||
AI_Sec ==VO_TimeStr.tm_sec ;
|
||
///////
|
||
}/*
|
||
static bool IsValidTime(time_t AI_Time, int AI_Year, int AI_Month, int AI_Day, int AI_Hour, int AI_Min, int AI_Sec, bool AB_IsLocalTime=true)*/
|
||
|
||
static bool IsValidTime(int AI_Year, int AI_Month, int AI_Day, int AI_Hour, int AI_Min, int AI_Sec, bool AB_IsLocalTime=true)
|
||
{
|
||
return IsValidTime(
|
||
MakeTimeInt(AI_Year, AI_Month, AI_Day, AI_Hour, AI_Min, AI_Sec),
|
||
AI_Year ,
|
||
AI_Month,
|
||
AI_Day ,
|
||
AI_Hour ,
|
||
AI_Min ,
|
||
AI_Sec ,
|
||
AB_IsLocalTime
|
||
/*/////////*/ ); ///////////////////////////////////////////////////////////////
|
||
}/*
|
||
static bool IsValidTime(int AI_Year, int AI_Month, int AI_Day, int AI_Hour, int AI_Min, int AI_Sec, bool AB_IsLocalTime=true)*/
|
||
|
||
|
||
bool Plus (time_t AI_TimeAddVal ){ml_TimeSec+=AI_TimeAddVal ; return SetTimeObj();}
|
||
bool Minus(time_t AI_TimeMinusVal){ml_TimeSec-=AI_TimeMinusVal; return SetTimeObj();}
|
||
|
||
ZCTime& operator+=(time_t AI_TimeVal){Plus (AI_TimeVal); return *this;}
|
||
ZCTime& operator-=(time_t AI_TimeVal){Minus(AI_TimeVal); return *this;}
|
||
|
||
|
||
char* GetTimeChars()
|
||
{
|
||
return ::asctime(&mo_TimeObj);
|
||
|
||
// We can see "Mon Nov 20Sun Jun 6 12:30:34 1995\n\0 " format from the function
|
||
// A size of char array which thie function return is 26
|
||
}/*
|
||
char* GetTimeChars()*/
|
||
|
||
inline int GetSysYear () const{return mo_TimeObj.tm_year ;}
|
||
inline int GetYear () const{return mo_TimeObj.tm_year + 1900 ;}
|
||
inline int GetSysMonth() const{return mo_TimeObj.tm_mon ;}
|
||
inline int GetMonth () const{return mo_TimeObj.tm_mon + 1 ;}
|
||
inline int GetDay () const{return mo_TimeObj.tm_mday ;}
|
||
inline int GetHour () const{return mo_TimeObj.tm_hour ;}
|
||
inline int GetMinute () const{return mo_TimeObj.tm_min ;}
|
||
inline int GetMin () const{return mo_TimeObj.tm_min ;}
|
||
inline int GetSecond () const{return mo_TimeObj.tm_sec ;}
|
||
inline int GetSec () const{return mo_TimeObj.tm_sec ;}
|
||
inline int GetYDay () const{return mo_TimeObj.tm_yday + 1 ;}
|
||
inline int GetSysYDay () const
|
||
{
|
||
// int tm_yday; // Day of year (0 - 365)
|
||
|
||
return mo_TimeObj.tm_yday ;
|
||
}/*
|
||
inline int GetSysYDay() const*/
|
||
|
||
inline int GetWeekDay() const
|
||
{
|
||
// int tm_wday; // Day of week (0 - 6 : 0 = Sunday)
|
||
|
||
return mo_TimeObj.tm_wday + 1 ;
|
||
}/*
|
||
inline int GetWeekDay() const*/
|
||
|
||
inline int GetSysWeekDay() const
|
||
{
|
||
// int tm_wday; // Day of week (0 - 6 : 0 = Sunday)
|
||
|
||
return mo_TimeObj.tm_wday ;
|
||
}/*
|
||
inline int GetSysWeekDay() const*/
|
||
|
||
inline int GetWeekOfYear() const
|
||
{
|
||
// 그 해의 몇 번째 주인지를 판단한다.
|
||
// int tm_wday; // Day of week (0 - 6 : 0 = Sunday)
|
||
|
||
if(mo_TimeObj.tm_yday<=mo_TimeObj.tm_wday) return 1;
|
||
|
||
ZTycInt CI_DayCntOfWeek= 7;
|
||
ZTycInt CI_DayCntAdded = 2;
|
||
|
||
return (mo_TimeObj.tm_yday - mo_TimeObj.tm_wday-1)/CI_DayCntOfWeek + CI_DayCntAdded ;
|
||
}/*
|
||
inline int GetWeekOfYear() const*/
|
||
|
||
inline char* GetDate(bool AB_DoHaveHypen=true)
|
||
{
|
||
// AB_DoHaveHypen=true 이면, 일자를 2007-01-01 형태로 반환한다.
|
||
// AB_DoHaveHypen=false 이면, 일자를 20070101 형태로 반환한다.
|
||
|
||
if(mpc_TimeBuff==0)
|
||
{
|
||
mpc_TimeBuff=new char[ZCTime::ETimeBuffSize+1];
|
||
|
||
if(mpc_TimeBuff==0)
|
||
{
|
||
// Add Codes For Memory Over;
|
||
|
||
return 0;
|
||
}/*
|
||
if(mpc_TimeBuff==0)*/
|
||
}/*
|
||
if(mpc_TimeBuff==0)*/
|
||
|
||
mpc_TimeBuff[0] =
|
||
mpc_TimeBuff[ZCTime::ETimeBuffSize]=0 ;
|
||
|
||
if(AB_DoHaveHypen)
|
||
{
|
||
(void)sprintf( mpc_TimeBuff ,
|
||
"%d-%02d-%02d" ,
|
||
GetYear(), GetMonth(), GetDay()
|
||
/*////////*/ );
|
||
}
|
||
else
|
||
{
|
||
(void)sprintf( mpc_TimeBuff ,
|
||
"%d%02d%02d" ,
|
||
GetYear(), GetMonth(), GetDay()
|
||
/*////////*/ );
|
||
}/*
|
||
else*/
|
||
|
||
return mpc_TimeBuff;
|
||
}/*
|
||
inline char* GetDate(bool AB_DoHaveHypen=true)*/
|
||
|
||
|
||
/*///////////////////////////////////////////////////////////////////////////
|
||
|
||
■ 일정 시간과의 차이를 초로 구한다.
|
||
일별로 로그 파일을 남길 때, 일자가 언제 바뀌는데 알고 싶을 때 사용할 수 있다.
|
||
특히 로그 쓰레드를 만들 때, 로그 쓰레드에서 어떤 신호를 받아 다른 날짜로 로그
|
||
파일명을 바꾸어야 한다면 이 로그 쓰레드의 날짜를 체크하는 타이머 쓰레드에서
|
||
이 값을 참고할 수 있다.
|
||
|
||
-- 2009-05-19 14:03:00
|
||
|
||
///////////////////////////////////////////////////////////////////////////*/
|
||
|
||
long GetDiffSec(int AI_Hour=24, int AI_Min=0, int AI_Sec=0)
|
||
{
|
||
return (AI_Hour*3600+AI_Min*60+AI_Sec) - (mo_TimeObj.tm_hour*3600 + mo_TimeObj.tm_min*60 + mo_TimeObj.tm_sec) ;
|
||
}/*
|
||
long GetDiffSec(int AI_Hour=24, int AI_Min=0, int AI_Sec=0)*/
|
||
|
||
bool GetDiffSec(time_t& ARRI_TimeGap, int AI_Year, int AI_Month, int AI_Day, int AI_Hour, int AI_Min, int AI_Sec)
|
||
{
|
||
time_t VI_TimeSec=ZNsMain::ZCTime::MakeTimeInt(AI_Year, AI_Month, AI_Day, AI_Hour, AI_Min, AI_Sec);
|
||
|
||
if(VI_TimeSec<1){return false;} *this+=VI_TimeSec; return true ;
|
||
}/*
|
||
bool GetDiffSec(time_t& ARRI_TimeGap, int AI_Year,int AI_Month,int AI_Day,int AI_Hour,int AI_Min,int AI_Sec)*/
|
||
|
||
static bool GetDiffSec(
|
||
time_t& ARRI_TimeGap,
|
||
int AI_Year1, int AI_Month1, int AI_Day1, int AI_Hour1, int AI_Min1, int AI_Sec1,
|
||
int AI_Year2 ,int AI_Month2, int AI_Day2, int AI_Hour2, int AI_Min2, int AI_Sec2
|
||
/*//////////*/ )
|
||
{
|
||
time_t VI_TimeSec1=ZNsMain::ZCTime::MakeTimeInt(AI_Year1, AI_Month1, AI_Day1, AI_Hour1, AI_Min1, AI_Sec1);
|
||
time_t VI_TimeSec2=ZNsMain::ZCTime::MakeTimeInt(AI_Year2, AI_Month2, AI_Day2, AI_Hour2, AI_Min2, AI_Sec2);
|
||
|
||
if(VI_TimeSec1<0 || VI_TimeSec2<0) return false;
|
||
|
||
ARRI_TimeGap=VI_TimeSec2-VI_TimeSec1; return true ;
|
||
}/*
|
||
static bool GetDiffSec(
|
||
time_t& ARRI_TimeGap,
|
||
int AI_Year1, int AI_Month1, int AI_Day1, int AI_Hour1, int AI_Min1, int AI_Sec1,
|
||
int AI_Year2 ,int AI_Month2, int AI_Day2, int AI_Hour2, int AI_Min2, int AI_Sec2
|
||
////////////// ) */
|
||
|
||
static inline long GetNowDiffSec(int AI_Hour=24, int AI_Min=0, int AI_Sec=0)
|
||
{
|
||
ZCTime VO_CTime; return VO_CTime.GetDiffSec(AI_Hour, AI_Min, AI_Sec);
|
||
}/*
|
||
static inline long GetNowDiffSec(int AI_Hour=24, int AI_Min=0, int AI_Sec=0)*/
|
||
|
||
|
||
inline char* GetTimeStamp()
|
||
{
|
||
if(mpc_TimeBuff==0)
|
||
{
|
||
mpc_TimeBuff=new char[ZCTime::ETimeBuffSize+1];
|
||
|
||
if(mpc_TimeBuff==0)
|
||
{
|
||
// Add Codes For Memory Over;
|
||
|
||
return 0;
|
||
}/*
|
||
if(mpc_TimeBuff==0)*/
|
||
}/*
|
||
if(mpc_TimeBuff==0)*/
|
||
|
||
mpc_TimeBuff[0] =
|
||
mpc_TimeBuff[ZCTime::ETimeBuffSize]=0 ;
|
||
|
||
(void)sprintf ///////////////////////////
|
||
(
|
||
mpc_TimeBuff,
|
||
"%d-%02d-%02d %02d:%02d:%02d" ,
|
||
GetYear(), GetMonth (), GetDay(),
|
||
GetHour(), GetMinute(), GetSec()
|
||
);
|
||
/////////////////////////////////////////
|
||
|
||
return mpc_TimeBuff;
|
||
}/*
|
||
inline char* GetTimeStamp()*/
|
||
inline char* GetTimeStamp2()
|
||
{
|
||
// GetTimeStamp() 와는 달리, 공백, '-', ':' 등을 없앤다. 2012-09-09 10:16:00
|
||
|
||
if(mpc_TimeBuff==0)
|
||
{
|
||
mpc_TimeBuff=new char[ZCTime::ETimeBuffSize+1];
|
||
|
||
if(mpc_TimeBuff==0)
|
||
{
|
||
// Add Codes For Memory Over;
|
||
|
||
return 0;
|
||
}/*
|
||
if(mpc_TimeBuff==0)*/
|
||
}/*
|
||
if(mpc_TimeBuff==0)*/
|
||
|
||
mpc_TimeBuff[0] =
|
||
mpc_TimeBuff[ZCTime::ETimeBuffSize]=0 ;
|
||
|
||
(void)sprintf /////////////////////////////////
|
||
(
|
||
mpc_TimeBuff, "%d%02d%02d%02d%02d%02d",
|
||
GetYear() , GetMonth (), GetDay() ,
|
||
GetHour() , GetMinute(), GetSec()
|
||
);
|
||
///////////////////////////////////////////////
|
||
|
||
return mpc_TimeBuff;
|
||
}/*
|
||
inline char* GetTimeStamp2()*/
|
||
|
||
static inline char* GetNowTimeStamp(bool AB_IsLoaclTime=true)
|
||
{
|
||
struct tm VO_StTime; time_t VL_Time; time(&VL_Time); /*##############*/
|
||
|
||
if(SetTimeObj(VL_Time, RR(VO_StTime), AB_IsLoaclTime)==false) return 0;
|
||
|
||
|
||
ZTycInt CI_TimeBuffSize=30; static char VCA_TimeBuff[CI_TimeBuffSize];
|
||
|
||
(void)sprintf ////////////////////////////////////////////////////////
|
||
(
|
||
VCA_TimeBuff , "%d-%02d-%02d %02d:%02d:%02d" ,
|
||
VO_StTime.tm_year+1900, VO_StTime.tm_mon+1, VO_StTime.tm_mday,
|
||
VO_StTime.tm_hour , VO_StTime.tm_min , VO_StTime.tm_sec
|
||
);
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
return VCA_TimeBuff;
|
||
}/*
|
||
static inline char* GetNowTimeStamp(bool AB_IsLoaclTime=true)*/
|
||
|
||
inline static char* GetTimeChars(const time_t& AR_TimeVal)
|
||
{
|
||
struct tm VO_StTime;
|
||
|
||
if(SetSystemTimeObj(AR_TimeVal, RR(VO_StTime))==false) return 0;
|
||
|
||
return ::asctime(&VO_StTime); /*##############################*/
|
||
}/*
|
||
inline static char* GetTimeChars(const time_t& AR_TimeVal)*/
|
||
|
||
inline static char* GetLocalTimeChars(const time_t& AR_TimeVal)
|
||
{
|
||
struct tm VO_StTime;
|
||
|
||
if(SetLocalTimeObj(AR_TimeVal, RR(VO_StTime))==false) return 0;
|
||
|
||
return ::asctime(&VO_StTime); /*#############################*/
|
||
}/*
|
||
inline static char* GetLocalTimeChars(const time_t& AR_TimeVal)*/
|
||
|
||
static inline time_t GetNowSec()
|
||
{
|
||
return time((time_t*)0); // Get Sec Time after the standard time
|
||
}/*
|
||
static inline time_t GetNowSec()*/
|
||
|
||
static inline clock_t Clock()
|
||
{
|
||
return clock(); // _CRTIMP clock_t __cdecl clock(void);
|
||
}/*
|
||
static inline clock_t Clock()*/
|
||
|
||
static inline long GetSecFromClock(clock_t AI_ClockInt)
|
||
{
|
||
return AI_ClockInt / CLOCKS_PER_SEC ;
|
||
}/*
|
||
static inline long GetSecFromClock(clock_t AI_ClockInt)*/
|
||
|
||
|
||
#if !defined(_WIN) // Is it better not to use this function ?
|
||
|
||
|
||
/*/////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ gcc 2.96 에서는 strptime 이 구현되지 않았을 수도 있다.
|
||
|
||
static inline char* GetTimeChars(const char* APC_Buff, const char* APC_Format, struct tm* AP_StTime)
|
||
{
|
||
return ::strptime(APC_Buff,APC_Format,AP_StTime);
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
static string& GetUniqueID(string& ARR_CString)
|
||
{
|
||
static int SI_Count=0;
|
||
|
||
const char* CPC_Gap="_" ;
|
||
char VCA_Buff[60] ;
|
||
|
||
struct timeval TTimeVal ;
|
||
struct timezone TTimeZone ;
|
||
|
||
gettimeofday(&TTimeVal,&TTimeZone);
|
||
|
||
(void)::sprintf ////////////////////////////
|
||
(
|
||
VCA_Buff, "%ld%s%ld%s%ld%s%ld%s%ld",
|
||
long(TTimeVal.tv_sec ) , CPC_Gap ,
|
||
long(TTimeVal.tv_usec) , CPC_Gap ,
|
||
long(getpid()) , CPC_Gap ,
|
||
long(getppid()) , CPC_Gap ,
|
||
long(++SI_Count)
|
||
);
|
||
////////////////////////////////////////////
|
||
|
||
return ARR_CString=VCA_Buff ;
|
||
}/*
|
||
static string& GetUniqueID(string& ARR_CString)*/
|
||
|
||
|
||
template<typename TTypString> static TTypString& GetUniqueIDObj(TTypString& ARR_CString)
|
||
{
|
||
static int SI_Count = 0 ;
|
||
|
||
const char* CPC_Gap="_" ;
|
||
char VCA_Buff[60] ;
|
||
|
||
struct timeval TTimeVal ;
|
||
struct timezone TTimeZone ;
|
||
|
||
gettimeofday(&TTimeVal,&TTimeZone);
|
||
|
||
(void)sprintf /////////////////////
|
||
(
|
||
VCA_Buff ,
|
||
"%ld%s%ld%s%ld%s%ld%s%ld" ,
|
||
TTimeVal.tv_sec , CPC_Gap ,
|
||
TTimeVal.tv_usec, CPC_Gap ,
|
||
getpid() , CPC_Gap ,
|
||
getppid() , CPC_Gap , ++SI_Count
|
||
);
|
||
///////////////////////////////////
|
||
|
||
return ARR_CString=VCA_Buff ;
|
||
}/*
|
||
template<typename TTypString> static TTypString& GetUniqueIDObj(TTypString& ARR_CString)*/
|
||
|
||
|
||
#else // deinfed(_WIN)
|
||
|
||
|
||
static string& GetUniqueID(string& ARR_CString)
|
||
{
|
||
const int CI_BuffSize=100 ;
|
||
static long SI_Count =0 ;
|
||
const char* CPC_Gap ="_" ;
|
||
char VCA_Buff[CI_BuffSize] ;
|
||
|
||
::sprintf( VCA_Buff,
|
||
"%ld%s%ld%s%ld" ,
|
||
(long)GetNowSec(), // (long) 가 없으면 메모리 오류가 난다.
|
||
CPC_Gap , (long)GetTickCount() ,
|
||
CPC_Gap , (++SI_Count)+long(::GetCurrentProcessId())
|
||
/*////*/ );
|
||
|
||
return ARR_CString = VCA_Buff ;
|
||
|
||
/*//////////////////////////////////////////////////////////////
|
||
|
||
■ sprintf
|
||
|
||
※ http://msdn.microsoft.com/en-us/library/ybk95axf.aspx In MSDN
|
||
|
||
// crt_sprintf.c
|
||
// compile with: /W3
|
||
// This program uses sprintf to format various
|
||
// data and place them in the string named buffer.
|
||
|
||
#include <stdio.h>
|
||
|
||
int main( void )
|
||
{
|
||
char buffer[200], s[] = "computer", c = 'l';
|
||
int i = 35, j;
|
||
float fp = 1.7320534f;
|
||
|
||
// Format and print various data:
|
||
j = sprintf( buffer, " String: %s\n", s ); // C4996
|
||
j += sprintf( buffer + j, " Character: %c\n", c ); // C4996
|
||
j += sprintf( buffer + j, " Integer: %d\n", i ); // C4996
|
||
j += sprintf( buffer + j, " Real: %f\n", fp );// C4996
|
||
// Note: sprintf is deprecated; consider using sprintf_s instead
|
||
|
||
printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
|
||
}
|
||
|
||
■ Windows C++ Safe String Functions
|
||
|
||
※ http://www.lingoport.com/gi/help/gihelp/unsafeMethod/winstrsafe.htm
|
||
|
||
Strsafe.h function Replaces
|
||
|
||
StringCchCat, StringCchCatEx strcat, wcscat, lstrcat, strcat, StrCatBuff, _tcscat, _ftcscat
|
||
StringCchCatN, StringCchCatNEx strncat, StrNCat
|
||
StringCchCopy, StringCchCopyEx strcpy, wcscpy, lstrcpy, strcpy, _tcscpy, _ftcscpy
|
||
StringCchCopyN, StringCchCopyNEx strncpy
|
||
StringCchGets, StringCchGetsEx gets, _getws, _getts
|
||
StringCchPrintf, StringCchPrintfEx sprintf, swprintf, wsprintf, wnsprintf, _stprintf, _snprintf, _snwprintf, _sntprintf
|
||
StringCchVPrintf, StringCchVPrintfEx vsprintf, vswprintf, wvsprintf, wvnsprintf, _vstprintf, _vsnprintf, _vsnwprintf, _vsntprintf
|
||
|
||
StringCchLength, strlen, lstrlen
|
||
|
||
■ GetTickCount()
|
||
|
||
Windows 가 부팅된 이후의 시간을 구하는데, 이전 GetTickCount()
|
||
호출과의 시간 간격은 약 49.7 일 동안은 유효하다.
|
||
|
||
//////////////////////////////////////////////////////////////*/
|
||
}/*
|
||
static string& GetUniqueID(string& ARR_CString)*/
|
||
|
||
|
||
template<typename TTypString>
|
||
static TTypString& GetUniqueIDObj(TTypString& ARR_CString)
|
||
{
|
||
static int SI_Count =0 ;
|
||
const int CI_BuffSize=100 ;
|
||
|
||
ZTypChar VC_Buff[CI_BuffSize];
|
||
ZTypCPCCh VP_GAP ="-" ;
|
||
|
||
(void)::sprintf
|
||
(
|
||
VC_Buff , "%d%s%d%s%d",
|
||
(long)GetNowSec() , VP_GAP ,
|
||
::GetTickCount() , VP_GAP ,
|
||
(++SI_Count) + ::GetCurrentProcessId()
|
||
);
|
||
/*###########*/
|
||
|
||
/*//////////////////////////////////////////////////////////
|
||
|
||
■ (long) 를 제거하면 VC++ 2008 에서 메모리 오류가 발생한다.
|
||
|
||
-- 2008-09-07 02:27:00
|
||
|
||
//////////////////////////////////////////////////////////*/
|
||
|
||
return ARR_CString=VC_Buff ;
|
||
}/*
|
||
template<typename TTypString>
|
||
static TTypString& GetUniqueIDObj(TTypString& ARR_CString) */
|
||
|
||
|
||
#endif //deinfed(_WIN)
|
||
|
||
|
||
static string& GetUniqueID()
|
||
{
|
||
static string VO_CStringObj; VO_CStringObj=""; return GetUniqueID(VO_CStringObj);
|
||
}/*
|
||
static string& GetUniqueID()*/
|
||
|
||
template<typename TTypString> static TTypString& GetUniqueIDObj()
|
||
{
|
||
static TTypString VO_CStringObj; VO_CStringObj="";
|
||
|
||
return GetUniqueIDObj<TTypString>(RR(VO_CStringObj));
|
||
}/*
|
||
template<typename TTypString> static TTypString& GetUniqueIDObj()*/
|
||
|
||
|
||
/*////////////////////////////////////////////////////////
|
||
|
||
clock
|
||
Calculates the wall-clock time used by the calling process.
|
||
|
||
clock_t clock( void );
|
||
Return Value
|
||
The elapsed wall-clock time since the start of the process (elapsed time in seconds times CLOCKS_PER_SEC). If the amount of elapsed time is unavailable, the function returns ?1, cast as a clock_t.
|
||
|
||
Remarks
|
||
The clock function tells how much time the calling process has used. A timer tick is approximately equal to 1/CLOCKS_PER_SEC second. In versions of Microsoft C before 6.0, the CLOCKS_PER_SEC constant was called CLK_TCK.
|
||
|
||
Requirements
|
||
Routine Required header Compatibility
|
||
clock <time.h> ANSI, Win 98, Win Me, Win NT, Win 2000, Win XP
|
||
|
||
For additional compatibility information, see Compatibility in the Introduction.
|
||
|
||
Libraries
|
||
|
||
All versions of the C run-time libraries.
|
||
|
||
Example
|
||
CLOCK.C: This example prompts for how long
|
||
the program is to run and then continuously
|
||
displays the elapsed time for that period.
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <time.h>
|
||
|
||
void sleep( clock_t wait );
|
||
|
||
void main( void )
|
||
{
|
||
long i = 600000L;
|
||
clock_t start, finish;
|
||
double duration;
|
||
|
||
// Delay for a specified time.
|
||
printf( "Delay for three seconds\n" );
|
||
sleep( (clock_t)3 * CLOCKS_PER_SEC );
|
||
printf( "Done!\n" );
|
||
|
||
// Measure the duration of an event.
|
||
printf( "Time to do %ld empty loops is ", i );
|
||
start = clock();
|
||
|
||
while( i-- )
|
||
{
|
||
};
|
||
|
||
finish = clock();
|
||
duration = (double)(finish - start) / CLOCKS_PER_SEC;
|
||
printf( "%2.1f seconds\n", duration );
|
||
}
|
||
|
||
// Pauses for a specified number of milliseconds.
|
||
|
||
void sleep( clock_t wait )
|
||
{
|
||
clock_t goal;
|
||
goal = wait + clock();
|
||
while( goal > clock() )
|
||
;
|
||
}
|
||
|
||
Output
|
||
Delay for three seconds
|
||
Done!
|
||
Time to do 600000 empty loops is 0.1 seconds
|
||
|
||
//////////////////////////////////////////////*/
|
||
|
||
public:
|
||
};/*
|
||
class ZCTime*/
|
||
|
||
|
||
#if defined(_WIN)
|
||
|
||
|
||
/*///////////////////////////////////////////////////////////
|
||
|
||
■ class ZCStdTime 클래스는 해당 OS 에 고유한 함수를 사용하여,
|
||
좀 더 multi-thread 에 안전하게 구현한다.
|
||
|
||
-- 2012-03-23 14:42:00
|
||
|
||
리눅스에서는 ZCTime 을 ZCStdTime 으로 typedef 해도 되는데, 현재
|
||
gettimeofday() 를 이용해 좀 더 최적화되었다. -- 2018-06-25 09:38:00
|
||
|
||
■ 현재 아래 멤버가 Unix 랑 호환되는 것으로 정했다.
|
||
|
||
ZCStdTime::TypeIntTime : 시간을 표현하는 정수 자료형.
|
||
|
||
ZCStdTime(bool AB_IsLocal=true)
|
||
|
||
void InitLocalTimeObj ()
|
||
void InitSystemTimeObj()
|
||
|
||
GetSecResolution()
|
||
|
||
GetTimeInt() : return os-dependent time value
|
||
GetTimeSec()
|
||
|
||
AddTimeIntMilli()
|
||
AddTimeIntSec ()
|
||
|
||
int GetYear ()
|
||
int GetMonth ()
|
||
int GetDay ()
|
||
int GetDayOfWeek() // sunday 가 0, monday 가 1.
|
||
int GetHour ()
|
||
int GetMinute ()
|
||
int GetSecond ()
|
||
int GetMin ()
|
||
int GetSec ()
|
||
int GetMilliSec ()
|
||
int GetMilli ()
|
||
|
||
|
||
-- 2012-04-02 17:25:00
|
||
|
||
■ -- In WinBase.h
|
||
|
||
typedef struct _SYSTEMTIME {
|
||
WORD wYear ;
|
||
WORD wMonth ;
|
||
WORD wDayOfWeek ;
|
||
WORD wDay ;
|
||
WORD wHour ;
|
||
WORD wMinute ;
|
||
WORD wSecond ;
|
||
WORD wMilliseconds;
|
||
} SYSTEMTIME, *PSYSTEMTIME
|
||
|
||
-- In WinDef.h
|
||
|
||
typedef struct _FILETIME {
|
||
DWORD dwLowDateTime ;
|
||
DWORD dwHighDateTime;
|
||
} FILETIME, *PFILETIME, *LPFILETIME;
|
||
#define _FILETIME_
|
||
|
||
□ 1601 년 1월 1일 0시가 기준이다.
|
||
time() 은 1970 년 1월 1일 0시가 기준이다.
|
||
|
||
□ FILETIME 타입은 그냥 간단하게 64비트 정수형으로 보면 되
|
||
는데 1601년 1월 1일 0시 0분 0초를 0으로 지정하며 1초에
|
||
10,000,000 이 늘어난다. 이를 두고 100 나노초의 해상도를
|
||
가진다고 이야기하는 것이다. 경과시간을 구할 때는 32비트
|
||
정수형 두개를 사용하지 않고 ULARGE_INTEGER 형에 대입한
|
||
후 QuadPart를 64비트 정수 연산을 이용한다. -- 2016-10-05
|
||
|
||
☞ http://blog.naver.com/mysticodoi/140043721556
|
||
|
||
아래 예제도 참고 -- 2018-06-21 17:08:00
|
||
|
||
☞ https://support.microsoft.com/ko-kr/help/188768/info-working-with-the-filetime-structure
|
||
|
||
#define _SECOND ((int64) 10000000)
|
||
#define _MINUTE (60 * _SECOND)
|
||
#define _HOUR (60 * _MINUTE)
|
||
#define _DAY (24 * _HOUR)
|
||
|
||
ULONGLONG qwResult;
|
||
|
||
// Copy the time into a quadword.
|
||
qwResult = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
|
||
|
||
// Add 30 days.
|
||
qwResult += 30 * _DAY;
|
||
|
||
// Copy the result back into the FILETIME structure.
|
||
ft.dwLowDateTime = (DWORD) (qwResult & 0xFFFFFFFF );
|
||
ft.dwHighDateTime = (DWORD) (qwResult >> 32 );
|
||
|
||
□ --
|
||
|
||
///////////////////////////////////////////////////////////*/
|
||
|
||
class ZCStdTime
|
||
{
|
||
public :
|
||
typedef ZTypUInt64 TypeIntTime;
|
||
private:
|
||
enum{ETimeBuffSize =30 };
|
||
enum{ESecResolution=1000*10000}; // 1 초를 이루는 값으로 1000 만.
|
||
private:
|
||
char mca_TimeBuff[ETimeBuffSize];
|
||
private:
|
||
bool mb_IsLocal ;
|
||
FILETIME mo_FILETIME ;
|
||
SYSTEMTIME mo_SYSTEMTIME;
|
||
public :
|
||
|
||
static TypeIntTime GetSecResolution()
|
||
{
|
||
return (TypeIntTime)ESecResolution;
|
||
}/*
|
||
static TypeIntTime GetSecResolution()*/
|
||
|
||
public :
|
||
|
||
ZCStdTime(bool AB_IsLoaclTime=true)
|
||
{
|
||
mb_IsLocal=AB_IsLoaclTime;
|
||
|
||
if(AB_IsLoaclTime)
|
||
InitLocalTimeObj ();
|
||
else InitSystemTimeObj();
|
||
}/*
|
||
ZCStdTime(bool AB_IsLoaclTime=true)*/
|
||
|
||
ZCStdTime(const ZCStdTime& rhs)
|
||
{
|
||
if(this==&rhs)
|
||
{
|
||
mb_IsLocal = true; return;
|
||
}
|
||
|
||
mb_IsLocal =rhs.mb_IsLocal ;
|
||
mo_FILETIME =rhs.mo_FILETIME ;
|
||
mo_SYSTEMTIME=rhs.mo_SYSTEMTIME;
|
||
}/*
|
||
ZCStdTime(const ZCStdTime& rhs)*/
|
||
|
||
~ZCStdTime()
|
||
{
|
||
}/*
|
||
~ZCStdTime()*/
|
||
|
||
ZCStdTime& operator=(const ZCStdTime& rhs)
|
||
{
|
||
if(this==&rhs) return *this;
|
||
|
||
mb_IsLocal =rhs.mb_IsLocal ;
|
||
mo_FILETIME =rhs.mo_FILETIME ;
|
||
mo_SYSTEMTIME=rhs.mo_SYSTEMTIME;
|
||
|
||
return *this;
|
||
}/*
|
||
ZCStdTime& operator=(const ZCStdTime& rhs)*/
|
||
|
||
|
||
bool InitLocalTimeObj()
|
||
{
|
||
::GetLocalTime (&mo_SYSTEMTIME); return
|
||
::SystemTimeToFileTime(&mo_SYSTEMTIME, &mo_FILETIME)==TRUE;
|
||
}/*
|
||
bool InitLocalTimeObj()*/
|
||
|
||
bool InitSystemTimeObj()
|
||
{
|
||
::GetSystemTime (&mo_SYSTEMTIME); return
|
||
::SystemTimeToFileTime(&mo_SYSTEMTIME, &mo_FILETIME)==TRUE;
|
||
}/*
|
||
bool InitSystemTimeObj()*/
|
||
|
||
bool InitTimeObj(bool AB_IsLoaclTime)
|
||
{
|
||
if(AB_IsLoaclTime)
|
||
return InitLocalTimeObj();
|
||
else
|
||
return InitSystemTimeObj();
|
||
//else
|
||
}/*
|
||
bool InitTimeObj(bool AB_IsLoaclTime)*/
|
||
|
||
bool InitTimeObj()
|
||
{
|
||
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
■ Windows 에서 CLogData.H 에서, 자꾸 mb_IsLocal 이 false 로 바뀌어 버린다.
|
||
그래서 __USE_LOCAL_TIME_BY_FORCE__ 이 정의되어 있으면, 무조건 InitTimeObj
|
||
에 false 를 전달한다. -- 2018-02-26 11:28:00
|
||
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
|
||
#ifdef __USE_LOCAL_TIME_BY_FORCE__
|
||
return InitTimeObj(true );
|
||
#else
|
||
return InitTimeObj(mb_IsLocal);
|
||
#endif
|
||
}/*
|
||
bool InitTimeObj()*/
|
||
|
||
bool InitTimeObjFromDate(
|
||
int AI_Year , int AI_Month, int AI_Day ,
|
||
int AI_Hour=0, int AI_Min=0, int AI_Sec=0, int AI_MiliSec=0)
|
||
{
|
||
mo_SYSTEMTIME.wYear =AI_Year ;
|
||
mo_SYSTEMTIME.wMonth =AI_Month ;
|
||
mo_SYSTEMTIME.wDay =AI_Day ;
|
||
mo_SYSTEMTIME.wHour =AI_Hour ;
|
||
mo_SYSTEMTIME.wMinute =AI_Min ;
|
||
mo_SYSTEMTIME.wSecond =AI_Sec ;
|
||
mo_SYSTEMTIME.wMilliseconds=AI_MiliSec;
|
||
mo_SYSTEMTIME.wDayOfWeek =0 ;
|
||
|
||
if(::SystemTimeToFileTime(&mo_SYSTEMTIME, &mo_FILETIME)==TRUE)
|
||
{
|
||
// to set mo_SYSTEMTIME.wDayOfWeek to correct value
|
||
|
||
::FileTimeToSystemTime(&mo_FILETIME, &mo_SYSTEMTIME); return true;
|
||
}/*
|
||
if(::SystemTimeToFileTime(&mo_SYSTEMTIME, &mo_FILETIME)==TRUE)*/
|
||
|
||
return false;
|
||
}/*
|
||
bool InitTimeObjFromDate(
|
||
int AI_Year , int AI_Month, int AI_Day ,
|
||
int AI_Hour=0, int AI_Min=0, int AI_Sec=0, int AI_MiliSec=0)*/
|
||
|
||
|
||
TypeIntTime GetTimeInt() const
|
||
{
|
||
return (((TypeIntTime)mo_FILETIME.dwHighDateTime)<<32) + mo_FILETIME.dwLowDateTime ;
|
||
}/*
|
||
TypeIntTime GetTimeInt() const*/
|
||
|
||
TypeIntTime GetTimeSec() const
|
||
{
|
||
return GetTimeInt()/ESecResolution;
|
||
}/*
|
||
TypeIntTime GetTimeSec() const*/
|
||
|
||
|
||
TypeIntTime AddTimeIntMilli(TypeIntTime AI_AddMilli) const{
|
||
return GetTimeInt() + ( AI_AddMilli*(ESecResolution/1000) ) ;}
|
||
TypeIntTime AddTimeIntSec (TypeIntTime AI_AddSec ) const{
|
||
return GetTimeInt() + ( AI_AddSec * ESecResolution ) ;}
|
||
|
||
|
||
inline TypeIntTime AddTimeIntMilliRev(TypeIntTime AI_AddMilli) const
|
||
{
|
||
// ESecResolution/1000 < 1 인 경우에는 1 milli 초를 표현할 수 없으니까,
|
||
// ESecResolution/1000 이상이면서 가장 가까운 배수로 보정(revise)하는
|
||
// 것이다. 스케줄러에서 예약 시간을 등록할 때 필요하다.
|
||
// ZCStdTime 에는 ESecResolution/1000 < 1 인 경우가 없어서, 사실상 이 함
|
||
// 수는 사용되지 않는다.
|
||
|
||
return AddTimeIntMilli(AI_AddMilli); // 특별한 처리가 필요없다.
|
||
}/*
|
||
inline TypeIntTime AddTimeIntMilliRev(TypeIntTime AI_AddMilli) const*/
|
||
|
||
inline TypeIntTime AddTimeIntSecRev(TypeIntTime AI_AddSec) const
|
||
{
|
||
// ESecResolution < 1 인 경우에는 1 초를 표현할 수 없으니까,
|
||
// ESecResolution 이상이면서 가장 가까운 배수로 보정(revise)하는
|
||
// 것이다. 스케줄러에서 예약 시간을 등록할 때 필요하다.
|
||
|
||
return AddTimeIntSec(AI_AddSec); // 특별한 처리가 필요없다.
|
||
}/*
|
||
inline TypeIntTime AddTimeIntSecRev(TypeIntTime AI_AddSec) const*/
|
||
|
||
|
||
int GetYear () const{return mo_SYSTEMTIME.wYear ;}
|
||
int GetMonth () const{return mo_SYSTEMTIME.wMonth ;}
|
||
int GetDay () const{return mo_SYSTEMTIME.wDay ;}
|
||
int GetDayOfWeek() const{return mo_SYSTEMTIME.wDayOfWeek ;} // sunday 가 0, monday 가 1.
|
||
int GetHour () const{return mo_SYSTEMTIME.wHour ;}
|
||
int GetMinute () const{return mo_SYSTEMTIME.wMinute ;}
|
||
int GetMin () const{return mo_SYSTEMTIME.wMinute ;}
|
||
int GetSecond () const{return mo_SYSTEMTIME.wSecond ;}
|
||
int GetSec () const{return mo_SYSTEMTIME.wSecond ;}
|
||
int GetMilliSec () const{return mo_SYSTEMTIME.wMilliseconds ;}
|
||
int GetMilli () const{return mo_SYSTEMTIME.wMilliseconds ;}
|
||
|
||
bool Plus(TypeIntTime AL_TimeSec)
|
||
{
|
||
TypeIntTime VL_TimeInt=GetTimeInt()+AL_TimeSec*ESecResolution;
|
||
|
||
mo_FILETIME.dwHighDateTime=(DWORD)(VL_TimeInt>>32 );
|
||
mo_FILETIME.dwLowDateTime =(DWORD)(VL_TimeInt & 0xFFFFFFFF);
|
||
|
||
return ::FileTimeToSystemTime(&mo_FILETIME, &mo_SYSTEMTIME)==TRUE;
|
||
}/*
|
||
bool Plus(TypeIntTime AL_TimeSec)*/
|
||
|
||
bool Minus(TypeIntTime AL_TimeSec)
|
||
{
|
||
TypeIntTime VL_TimeInt=GetTimeInt()-AL_TimeSec*ESecResolution;
|
||
|
||
mo_FILETIME.dwHighDateTime=(DWORD)(VL_TimeInt>>32 );
|
||
mo_FILETIME.dwLowDateTime =(DWORD)(VL_TimeInt & 0xFFFFFFFF);
|
||
|
||
return ::FileTimeToSystemTime(&mo_FILETIME, &mo_SYSTEMTIME)==TRUE;
|
||
}/*
|
||
bool Minus(TypeIntTime AL_TimeSec)*/
|
||
|
||
char* GetDate(bool AB_DoIncludeSpace=true)
|
||
{
|
||
// AB_DoIncludeSpace==true 이면 일자를 2007-01-01 형태로 반환한다.
|
||
// AB_DoIncludeSpace==false 이면 일자를 20070101 형태로 반환한다.
|
||
|
||
mca_TimeBuff[0] =
|
||
mca_TimeBuff[ZCStdTime::ETimeBuffSize]=0 ;
|
||
|
||
if(AB_DoIncludeSpace==true)
|
||
{
|
||
(void)::sprintf(mca_TimeBuff ,
|
||
"%d-%02d-%02d" ,
|
||
GetYear(), GetMonth(), GetDay()
|
||
/*//////////*/ );
|
||
}
|
||
else
|
||
{
|
||
(void)::sprintf(mca_TimeBuff ,
|
||
"%d%02d%02d" ,
|
||
GetYear(), GetMonth(), GetDay()
|
||
/*//////////*/ );
|
||
}/*
|
||
else*/
|
||
|
||
return mca_TimeBuff;
|
||
}/*
|
||
char* GetDate(bool AB_DoIncludeSpace=true)*/
|
||
|
||
char* GetTimeStamp()
|
||
{
|
||
mca_TimeBuff[0] =
|
||
mca_TimeBuff[ZCStdTime::ETimeBuffSize]=0 ;
|
||
|
||
(void)::sprintf(mca_TimeBuff,
|
||
"%d-%02d-%02d %02d:%02d:%02d",
|
||
GetYear(), GetMonth (), GetDay (),
|
||
GetHour(), GetMinute(), GetSecond()
|
||
/*//////////*/ );
|
||
|
||
return mca_TimeBuff;
|
||
}/*
|
||
char* GetTimeStamp()*/
|
||
|
||
public:
|
||
};/*
|
||
class ZCStdTime*/
|
||
|
||
|
||
/*///////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ class ZCTimeElapse
|
||
|
||
걸린 시간을 측정하는데, GetTickCount() 를 사용하고 있다. 좀 더 정확한 시간은 timeGetTime()
|
||
이나 아래 함수를 사용해야 한다.
|
||
|
||
QueryPerformanceCounter(StartTick);
|
||
QueryPerformanceFrequency(Freq);
|
||
|
||
또한 GetTickCount64() 하는 함수도 있는데, 게임 서버 같이, 장시간에 결쳐 운영되는 프로그램
|
||
에서 쓸 수 있겠다.
|
||
|
||
ULONGLONG WINAPI GetTickCount64(void);
|
||
|
||
-- 2013-08-11 01:17:00
|
||
|
||
■ http://cafe446.daum.net/_c21_/bbs_search_read?grpid=1EeeD&fldid=5AuH&contentval=0000bzzzzzzzzzzzzzzzzzzzzzzzzz&q=
|
||
|
||
[C언어 씨언어 알고니즘 정보보안전문가] - GetTickCount() - clock()보다 더 정확한 시간 재기.
|
||
|
||
>저도 GetTickCount가 어떤건지, 며칠전에 알았습니다.
|
||
>저처럼 모르고있었던분들도 있을것 같아서, 한번 올립니다.
|
||
>
|
||
>GetTickCount가 뭔 CPU클럭인가 먼가 .. 여튼 그런걸 이용한다던데요..
|
||
>여튼, 0.001초마다 이 카운트가 1씩 오르는건 정확합니다.
|
||
|
||
정확하지 않습니다.
|
||
카운트가 1ms(0.001sec) 라는건 값을 반환할 때 사용하는 단위가 밀리세컨드라는 뜻일 뿐입니다.
|
||
실제로 사용해보면 resolution(정밀도)은 15ms 정도에 불과합니다. (windows 2000 이상 기준)
|
||
|
||
winmm.lib 에 들어있는 (헤더는 mmsystem.h) timeGetTime() 함수가 좀 더 정확합니다.
|
||
|
||
대신 timeBeginPeriod() 와 timeEndPeriod() 함수로 정밀도를 수동조절해야 그나마 높은 정밀도
|
||
가 나옵니다. 문제는 그렇게 해놓아도 종종 10ms 이상의 점핑현상이 나타난다는거..
|
||
|
||
1ms 이상의 정밀도가 나오는 함수는 QueryPerformanceCounter() 이거 하나 뿐입니다. (수백만분
|
||
의 1초 수준의 정밀도가 나온다는군요)
|
||
|
||
이 함수의 문제는 하드웨어 사양에 따라 지원이 안되거나, 이상한 결과가 나올 수도 있다는 점..
|
||
|
||
결론을 말하자면, 윈도우즈에서 1ms 정밀도에 안정성까지 있는 함수는 존재하지 않습니다.
|
||
|
||
저는 라이브러리 로딩할 때 QueryPerformanceCounter() 가 지원되는지를 한번 확인하고, 지원 안
|
||
된다면 그냥 GetTickCount()를 쓰되 오차를 적절히 보정해서 씁니다.
|
||
|
||
그러나 1/100초 정도의 정밀도로 충분하다면 GetTickCount() 를 쓰는게 좋습니다
|
||
|
||
-- 2013-08-11 01:17:00
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
class ZCTimeElapse
|
||
{
|
||
public :
|
||
typedef ZTypInt64 TypeIntTime;
|
||
private:
|
||
TypeIntTime ml_InitMiliTime ;
|
||
public :
|
||
|
||
ZCTimeElapse()
|
||
{
|
||
ml_InitMiliTime = ::GetTickCount();
|
||
}/*
|
||
ZCTimeElapse()*/
|
||
|
||
void Init()
|
||
{
|
||
ml_InitMiliTime = ::GetTickCount();
|
||
}/*
|
||
void Init()*/
|
||
|
||
TypeIntTime GetElapse() const
|
||
{
|
||
return ::GetTickCount()-ml_InitMiliTime;
|
||
}/*
|
||
TypeIntTime GetElapse() const*/
|
||
|
||
TypeIntTime GetElapseInit() // 시간 간격을 구하면서 동시에 초기화를 한다.
|
||
{
|
||
long VL_PrevTime=ml_InitMiliTime;
|
||
|
||
ml_InitMiliTime = ::GetTickCount();
|
||
|
||
return ml_InitMiliTime-VL_PrevTime;
|
||
}/*
|
||
TypeIntTime GetElapseInit()*/
|
||
|
||
TypeIntTime GetTimeInt () const{return ml_InitMiliTime;}
|
||
TypeIntTime GetTimeMilli() const{return ml_InitMiliTime;}
|
||
|
||
static TypeIntTime GetTimeIntNow () { return ::GetTickCount(); }
|
||
static TypeIntTime GetTimeMilliNow() { return ::GetTickCount(); }
|
||
|
||
public:
|
||
};/*
|
||
class ZCTimeElapse*/
|
||
|
||
|
||
#else // !defined(_WIN)
|
||
|
||
|
||
/*//////////////////////////////////////////////////////////////
|
||
|
||
■ ZCTime 에 동기화 처리가 되었기 때문에, Unix 에서는 ZCTime 을
|
||
ZCStdTime 으로 typedef 해서 사용한다.
|
||
|
||
-- 2012-04-03 12:45:00
|
||
|
||
이제는 Unix 에서 gettimeofday() 를 이용한 좀 더 최적화된 ZCStdTime
|
||
을 만들었다. -- 2018-06-22 14:47:00
|
||
|
||
■ HP-UX 에서는 localtime_r, gmtime_r 을 사용하기 위해서는
|
||
_REENTRANT 을 정의해야 하는 경우가 있다.
|
||
|
||
-- 2012-04-08 18:43:00
|
||
|
||
//////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
class ZCStdTime
|
||
{
|
||
public :
|
||
typedef ZTypInt64 TypeIntTime;
|
||
private:
|
||
enum{ETimeBuffSize =30 };
|
||
enum{ESecResolution=1000*1000 }; // 1 초를 이루는 값으로 100 만.
|
||
private:
|
||
char mca_TimeBuff[ETimeBuffSize];
|
||
private:
|
||
bool mb_IsLocal; struct
|
||
timeval mo_TimeVal; struct
|
||
tm mo_TimeObj;
|
||
TypeIntTime mi_TimeSec;
|
||
public :
|
||
|
||
static TypeIntTime GetSecResolution()
|
||
{
|
||
return (TypeIntTime)ESecResolution;
|
||
}/*
|
||
static TypeIntTime GetSecResolution()*/
|
||
|
||
public :
|
||
|
||
ZCStdTime(bool AB_IsLoaclTime=true)
|
||
{
|
||
mb_IsLocal=AB_IsLoaclTime;
|
||
mi_TimeSec=0 ;
|
||
|
||
if(AB_IsLoaclTime)
|
||
InitLocalTimeObj ();
|
||
else InitSystemTimeObj();
|
||
}/*
|
||
ZCStdTime(bool AB_IsLoaclTime=true)*/
|
||
|
||
ZCStdTime(const ZCStdTime& rhs)
|
||
{
|
||
mb_IsLocal=rhs.mb_IsLocal;
|
||
mo_TimeVal=rhs.mo_TimeVal;
|
||
mo_TimeObj=rhs.mo_TimeObj;
|
||
mi_TimeSec=rhs.mi_TimeSec;
|
||
}/*
|
||
ZCStdTime(const ZCStdTime& rhs)*/
|
||
|
||
~ZCStdTime()
|
||
{
|
||
}/*
|
||
~ZCStdTime()*/
|
||
|
||
ZCStdTime& operator=(const ZCStdTime& rhs)
|
||
{
|
||
if(this==&rhs) return *this;
|
||
|
||
mb_IsLocal=rhs.mb_IsLocal;
|
||
mo_TimeVal=rhs.mo_TimeVal;
|
||
mo_TimeObj=rhs.mo_TimeObj;
|
||
mi_TimeSec=rhs.mi_TimeSec;
|
||
|
||
return *this;
|
||
}/*
|
||
ZCStdTime& operator=(const ZCStdTime& rhs)*/
|
||
|
||
|
||
bool InitLocalTimeObj()
|
||
{
|
||
::gettimeofday(&mo_TimeVal, NULL );
|
||
::localtime_r (&mo_TimeVal.tv_sec, &mo_TimeObj); return true;
|
||
}/*
|
||
bool InitLocalTimeObj()*/
|
||
|
||
bool InitSystemTimeObj()
|
||
{
|
||
::gettimeofday(&mo_TimeVal, NULL );
|
||
::gmtime_r (&mo_TimeVal.tv_sec, &mo_TimeObj); return true;
|
||
}/*
|
||
bool InitSystemTimeObj()*/
|
||
|
||
bool InitTimeObj(bool AB_IsLoaclTime)
|
||
{
|
||
if(AB_IsLoaclTime)
|
||
return InitLocalTimeObj ();
|
||
else return InitSystemTimeObj();
|
||
}/*
|
||
bool InitTimeObj(bool AB_IsLoaclTime)*/
|
||
|
||
bool InitTimeObj()
|
||
{
|
||
return InitTimeObj(mb_IsLocal);
|
||
}/*
|
||
bool InitTimeObj()*/
|
||
|
||
|
||
bool InitLocalTimeObj(TypeIntTime AI_TimeInt)
|
||
{
|
||
if(::localtime_r(&AI_TimeInt, &mo_TimeObj)==0)
|
||
return false;
|
||
/*##########################################*/
|
||
|
||
mi_TimeSec = AI_TimeInt;
|
||
mo_TimeVal.tv_sec = AI_TimeInt;
|
||
mo_TimeVal.tv_usec= 0 ; return true;
|
||
}/*
|
||
bool InitLocalTimeObj()*/
|
||
|
||
bool InitSystemTimeObj(TypeIntTime AI_TimeInt)
|
||
{
|
||
if(::gmtime_r(&AI_TimeInt, &mo_TimeObj)==0)
|
||
return false;
|
||
/*#######################################*/
|
||
|
||
mi_TimeSec = AI_TimeInt;
|
||
mo_TimeVal.tv_sec = AI_TimeInt;
|
||
mo_TimeVal.tv_usec= 0 ; return true;
|
||
}/*
|
||
bool InitSystemTimeObj(TypeIntTime AI_TimeInt)*/
|
||
|
||
bool InitTimeObj(bool AB_IsLoaclTime, TypeIntTime AI_TimeInt)
|
||
{
|
||
if(AB_IsLoaclTime)
|
||
return InitLocalTimeObj (AI_TimeInt);
|
||
else return InitSystemTimeObj(AI_TimeInt);
|
||
}/*
|
||
bool InitTimeObj(bool AB_IsLoaclTime, TypeIntTime AI_TimeInt)*/
|
||
|
||
|
||
bool InitTimeObjFromDate(
|
||
int AI_Year , int AI_Month, int AI_Day ,
|
||
int AI_Hour=0, int AI_Min=0, int AI_Sec=0, int AI_MiliSec=0)
|
||
{
|
||
::memset(&mo_TimeVal, 0, sizeof(::tm));
|
||
|
||
mo_TimeObj.tm_year=AI_Year-1900 ;
|
||
mo_TimeObj.tm_mon =AI_Month-1 ;
|
||
mo_TimeObj.tm_mday=AI_Day ;
|
||
mo_TimeObj.tm_hour=AI_Hour ;
|
||
mo_TimeObj.tm_min =AI_Min ;
|
||
mo_TimeObj.tm_sec =AI_Sec ;
|
||
|
||
mi_TimeSec = ::mktime(&mo_TimeObj);
|
||
|
||
if(mi_TimeSec<=0) return false;
|
||
|
||
mo_TimeVal.tv_sec = mi_TimeSec ;
|
||
mo_TimeVal.tv_usec = AI_MiliSec*1000;
|
||
|
||
return true;
|
||
}/*
|
||
bool InitTimeObjFromDate(
|
||
int AI_Year , int AI_Month, int AI_Day ,
|
||
int AI_Hour=0, int AI_Min=0, int AI_Sec=0, int AI_MiliSec=0)*/
|
||
|
||
|
||
TypeIntTime GetTimeInt() const
|
||
{
|
||
return (((TypeIntTime)mo_TimeVal.tv_sec)<<32) + mo_TimeVal.tv_usec ;
|
||
}/*
|
||
TypeIntTime GetTimeInt() const*/
|
||
|
||
TypeIntTime GetTimeSec() const
|
||
{
|
||
return mo_TimeVal.tv_sec ;
|
||
}/*
|
||
TypeIntTime GetTimeSec() const*/
|
||
|
||
|
||
TypeIntTime AddTimeIntMilli(TypeIntTime AI_AddMilli) const{
|
||
return GetTimeInt() + ( AI_AddMilli*(ESecResolution/1000) ) ;}
|
||
TypeIntTime AddTimeIntSec (TypeIntTime AI_AddSec ) const{
|
||
return GetTimeInt() + ( AI_AddSec * ESecResolution ) ;}
|
||
|
||
|
||
inline TypeIntTime AddTimeIntMilliRev(TypeIntTime AI_AddMilli) const
|
||
{
|
||
// ESecResolution/1000 < 1 인 경우에는 1 milli 초를 표현할 수 없으니까,
|
||
// ESecResolution/1000 이상이면서 가장 가까운 배수로 보정(revise)하는
|
||
// 것이다. 스케줄러에서 예약 시간을 등록할 때 필요하다.
|
||
|
||
return AddTimeIntMilli(AI_AddMilli); // 특별한 처리가 필요없다.
|
||
}/*
|
||
inline TypeIntTime AddTimeIntMilliRev(TypeIntTime AI_AddMilli) const*/
|
||
|
||
inline TypeIntTime AddTimeIntSecRev(TypeIntTime AI_AddSec) const
|
||
{
|
||
// ESecResolution < 1 인 경우에는 1 초를 표현할 수 없으니까,
|
||
// ESecResolution 이상이면서 가장 가까운 배수로 보정(revise)하는
|
||
// 것이다. 스케줄러에서 예약 시간을 등록할 때 필요하다.
|
||
|
||
return AddTimeIntSec(AI_AddSec); // 특별한 처리가 필요없다.
|
||
}/*
|
||
inline TypeIntTime AddTimeIntSecRev(TypeIntTime AI_AddSec) const*/
|
||
|
||
|
||
inline int GetSysYear () const{return mo_TimeObj.tm_year ;}
|
||
inline int GetYear () const{return mo_TimeObj.tm_year + 1900 ;}
|
||
inline int GetSysMonth() const{return mo_TimeObj.tm_mon ;}
|
||
inline int GetMonth () const{return mo_TimeObj.tm_mon + 1 ;}
|
||
inline int GetDay () const{return mo_TimeObj.tm_mday ;}
|
||
inline int GetHour () const{return mo_TimeObj.tm_hour ;}
|
||
inline int GetMinute () const{return mo_TimeObj.tm_min ;}
|
||
inline int GetMin () const{return mo_TimeObj.tm_min ;}
|
||
inline int GetSecond () const{return mo_TimeObj.tm_sec ;}
|
||
inline int GetSec () const{return mo_TimeObj.tm_sec ;}
|
||
inline int GetYDay () const{return mo_TimeObj.tm_yday + 1 ;}
|
||
inline int GetSysYDay () const
|
||
{
|
||
// int tm_yday; // Day of year (0 - 365)
|
||
|
||
return mo_TimeObj.tm_yday ;
|
||
}/*
|
||
inline int GetSysYDay() const*/
|
||
|
||
inline int GetWeekDay() const
|
||
{
|
||
// int tm_wday; // Day of week (0 - 6 : 0 = Sunday)
|
||
|
||
return mo_TimeObj.tm_wday + 1 ;
|
||
}/*
|
||
inline int GetWeekDay() const*/
|
||
|
||
inline int GetSysWeekDay() const
|
||
{
|
||
// int tm_wday; // Day of week (0 - 6 : 0 = Sunday)
|
||
|
||
return mo_TimeObj.tm_wday ;
|
||
}/*
|
||
inline int GetSysWeekDay() const*/
|
||
|
||
inline int GetWeekOfYear() const
|
||
{
|
||
// 그 해의 몇 번째 주인지를 판단한다.
|
||
// int tm_wday; // Day of week (0 - 6 : 0 = Sunday)
|
||
|
||
if(mo_TimeObj.tm_yday<=mo_TimeObj.tm_wday) return 1;
|
||
|
||
ZTycInt CI_DayCntOfWeek=7;
|
||
ZTycInt CI_DayCntAdded =2;
|
||
|
||
return (mo_TimeObj.tm_yday - mo_TimeObj.tm_wday-1)/CI_DayCntOfWeek + CI_DayCntAdded ;
|
||
}/*
|
||
inline int GetWeekOfYear() const*/
|
||
|
||
int GetMilliSec() const{return mo_TimeVal.tv_usec/1000;}
|
||
int GetMilli () const{return mo_TimeVal.tv_usec/1000;}
|
||
int GetMicroSec() const{return mo_TimeVal.tv_usec ;}
|
||
|
||
|
||
bool Plus(TypeIntTime AL_TimeSec)
|
||
{
|
||
return InitTimeObj(mb_IsLocal, mo_TimeVal.tv_sec+AL_TimeSec);
|
||
}/*
|
||
bool Plus(TypeIntTime AL_TimeSec)*/
|
||
|
||
bool Minus(TypeIntTime AL_TimeSec)
|
||
{
|
||
return InitTimeObj(mb_IsLocal, mo_TimeVal.tv_sec-AL_TimeSec);
|
||
}/*
|
||
bool Minus(TypeIntTime AL_TimeSec)*/
|
||
|
||
char* GetDate(bool AB_DoIncludeSpace=true)
|
||
{
|
||
// AB_DoIncludeSpace==true 이면 일자를 2007-01-01 형태로 반환한다.
|
||
// AB_DoIncludeSpace==false 이면 일자를 20070101 형태로 반환한다.
|
||
|
||
mca_TimeBuff[0] =
|
||
mca_TimeBuff[ZCStdTime::ETimeBuffSize]=0 ;
|
||
|
||
if(AB_DoIncludeSpace==true)
|
||
{
|
||
(void)::sprintf(mca_TimeBuff ,
|
||
"%d-%02d-%02d" ,
|
||
GetYear(),GetMonth(),GetDay()
|
||
/*//////////*/ );
|
||
}
|
||
else
|
||
{
|
||
(void)::sprintf(mca_TimeBuff ,
|
||
"%d%02d%02d" ,
|
||
GetYear(),GetMonth(),GetDay()
|
||
/*//////////*/ );
|
||
}/*
|
||
else*/
|
||
|
||
return mca_TimeBuff;
|
||
}/*
|
||
char* GetDate(bool AB_DoIncludeSpace=true)*/
|
||
|
||
char* GetTimeStamp()
|
||
{
|
||
mca_TimeBuff[0] =
|
||
mca_TimeBuff[ZCStdTime::ETimeBuffSize]=0 ;
|
||
|
||
(void)::sprintf(mca_TimeBuff,
|
||
"%d-%02d-%02d %02d:%02d:%02d",
|
||
GetYear(), GetMonth (), GetDay (),
|
||
GetHour(), GetMinute(), GetSecond()
|
||
/*//////////*/ );
|
||
|
||
return mca_TimeBuff;
|
||
}/*
|
||
char* GetTimeStamp()*/
|
||
|
||
public:
|
||
};/*
|
||
class ZCStdTime*/
|
||
|
||
|
||
/*//////////////////////////////////////////////////////////////
|
||
|
||
■ struct timeval
|
||
{
|
||
time_t tv_sec ; // seconds
|
||
suseconds_t tv_usec; // microseconds
|
||
};
|
||
|
||
//////////////////////////////////////////////////////////////*/
|
||
|
||
class ZCTimeElapse
|
||
{
|
||
public :
|
||
typedef ZTypInt64 TypeIntTime ;
|
||
private:
|
||
struct timeval mo_InitTimeVal;
|
||
public :
|
||
|
||
ZCTimeElapse()
|
||
{
|
||
::gettimeofday(&mo_InitTimeVal, NULL);
|
||
}/*
|
||
ZCTimeElapse()*/
|
||
|
||
void Init()
|
||
{
|
||
::gettimeofday(&mo_InitTimeVal, NULL);
|
||
}/*
|
||
void Init()*/
|
||
|
||
ZTypInt64 GetElapse() const // 밀리 초로 반환한다.
|
||
{
|
||
struct timeval VO_TimeVal; ::gettimeofday(&VO_TimeVal, NULL);
|
||
|
||
return
|
||
(VO_TimeVal.tv_sec - mo_InitTimeVal.tv_sec )*1000 +
|
||
(VO_TimeVal.tv_usec- mo_InitTimeVal.tv_usec)/1000 ;
|
||
}/*
|
||
ZTypInt64 GetElapse() const*/
|
||
|
||
ZTypInt64 GetElapseInit() // 시간 간격을 구하면서 동시에 초기화를 한다.
|
||
{
|
||
struct timeval VO_TimeVal; ::gettimeofday(&VO_TimeVal, NULL);
|
||
|
||
long VL_MiliTime =
|
||
(VO_TimeVal.tv_sec - mo_InitTimeVal.tv_sec )*1000 +
|
||
(VO_TimeVal.tv_usec- mo_InitTimeVal.tv_usec)/1000 ;
|
||
|
||
mo_InitTimeVal=VO_TimeVal; return VL_MiliTime; ////////
|
||
}/*
|
||
ZTypInt64 GetElapseInit()*/
|
||
|
||
TypeIntTime GetTimeInt() const
|
||
{
|
||
return (TypeIntTime)(mo_InitTimeVal.tv_sec<<32) + mo_InitTimeVal.tv_usec;
|
||
}/*
|
||
TypeIntTime GetTimeInt() const*/
|
||
|
||
TypeIntTime GetTimeMilli() const
|
||
{
|
||
return (TypeIntTime)(mo_InitTimeVal.tv_sec*1000) + mo_InitTimeVal.tv_usec/1000;
|
||
}/*
|
||
TypeIntTime GetTimeMilli() const*/
|
||
|
||
static TypeIntTime GetTimeIntNow()
|
||
{
|
||
struct timeval VO_TimeVal; ::gettimeofday(&VO_TimeVal, NULL);
|
||
|
||
return (TypeIntTime)(VO_TimeVal.tv_sec<<32) + VO_TimeVal.tv_usec;
|
||
}/*
|
||
static TypeIntTime GetTimeIntNow()*/
|
||
|
||
static TypeIntTime GetTimeMilliNow()
|
||
{
|
||
// GetTimeIntNow() 을 milli 초로 환산한 것.
|
||
|
||
struct timeval VO_TimeVal; ::gettimeofday(&VO_TimeVal, NULL);
|
||
|
||
return (TypeIntTime)(VO_TimeVal.tv_sec )*1000 + (VO_TimeVal.tv_usec)/1000 ;
|
||
}/*
|
||
static TypeIntTime GetTimeMilliNow()*/
|
||
|
||
public:
|
||
};/*
|
||
class ZCTimeElapse*/
|
||
|
||
|
||
#endif // !defined(_WIN)
|
||
|
||
|
||
/*/////////////////////////////////////////////////////
|
||
|
||
Open a file.
|
||
|
||
int _open(
|
||
const char *filename,
|
||
int oflag [,
|
||
int pmode]
|
||
);
|
||
int _wopen(
|
||
const wchar_t *filename,
|
||
int oflag [,
|
||
int pmode]
|
||
);
|
||
|
||
Parameters
|
||
filename
|
||
Filename.
|
||
oflag
|
||
Type of operations allowed.
|
||
pmode
|
||
Permission mode.
|
||
Return Value
|
||
Each of these functions returns a file handle for the opened file.
|
||
A return value of ?1 indicates an error,
|
||
in which case errno is set to one of the following values:
|
||
|
||
EACCES
|
||
Tried to open read-only file for writing,
|
||
or file's sharing mode does not allow specified operations, or given path is directory.
|
||
EEXIST
|
||
_O_CREAT and _O_EXCL flags specified, but filename already exists.
|
||
EINVAL
|
||
Invalid oflag or pmode argument.
|
||
EMFILE
|
||
No more file handles available (too many open files).
|
||
ENOENT
|
||
File or path not found.
|
||
|
||
See _doserrno, errno, _sys_errlist, and _sys_nerr for more information on these,
|
||
and other, return codes.
|
||
|
||
Remarks
|
||
|
||
The _open function opens the file specified by filename and prepares the file
|
||
for reading or writing,
|
||
as specified by oflag. _wopen is a wide-character version of _open;
|
||
the filename argument to _wopen is a wide-character string.
|
||
_wopen and _open behave identically otherwise.
|
||
|
||
Generic-Text Routine Mappings
|
||
|
||
TCHAR.H routine _UNICODE & _MBCS not defined _MBCS defined _UNICODE defined
|
||
_topen _open _open _wopen
|
||
|
||
oflag is an integer expression formed
|
||
from one or more of the following manifest constants or constant combinations
|
||
defined in FCNTL.H:
|
||
|
||
_O_APPEND
|
||
Moves file pointer to end of file before every write operation.
|
||
_O_BINARY
|
||
Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
|
||
_O_CREAT
|
||
Creates and opens new file for writing. Has no effect if file specified by filename exists. pmode argument is required when _O_CREAT is specified.
|
||
_O_CREAT | _O_SHORT_LIVED
|
||
Create file as temporary and if possible do not flush to disk. pmode argument is required when _O_CREAT is specified.
|
||
_O_CREAT | _O_TEMPORARY
|
||
Create file as temporary; file is deleted when last file handle is closed. pmode argument is required when _O_CREAT is specified.
|
||
_O_CREAT | _O_EXCL
|
||
Returns error value if file specified by filename exists. Applies only when used with _O_CREAT.
|
||
_O_RANDOM
|
||
Specifies that caching is optimized for, but not restricted to, random access from disk.
|
||
_O_RDONLY
|
||
Opens file for reading only; cannot be specified with _O_RDWR or _O_WRONLY.
|
||
_O_RDWR
|
||
Opens file for both reading and writing; you cannot specify this flag with _O_RDONLY or _O_WRONLY.
|
||
_O_SEQUENTIAL
|
||
Specifies that caching is optimized for, but not restricted to, sequential access from disk.
|
||
_O_TEXT
|
||
Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
|
||
_O_TRUNC
|
||
Opens file and truncates it to zero length; file must have write permission. You cannot specify this flag with _O_RDONLY. _O_TRUNC used with _O_CREAT opens an existing file or creates a new file.
|
||
Note The _O_TRUNC flag destroys the contents of the specified file.
|
||
_O_WRONLY
|
||
Opens file for writing only; cannot be specified with _O_RDONLY or _O_RDWR.
|
||
|
||
To specify the file access mode,
|
||
you must specify either _O_RDONLY, _O_RDWR, or _O_WRONLY.
|
||
There is no default value for the access mode.
|
||
|
||
When two or more manifest constants are used to form the oflag argument,
|
||
the constants are combined with the bitwise-OR operator ( | ).
|
||
See Text and Binary Mode File I/O for a discussion of binary and text modes.
|
||
|
||
The pmode argument is required only when _O_CREAT is specified.
|
||
If the file already exists, pmode is ignored.
|
||
Otherwise, pmode specifies the file permission settings,
|
||
which are set when the new file is closed the first time.
|
||
_open applies the current file-permission mask to pmode before setting the permissions
|
||
(for more information, see _umask).
|
||
pmode is an integer expression containing one or both of the following manifest constants,
|
||
defined in SYS\STAT.H:
|
||
|
||
#define _S_IREAD 0000400 // read permission, owner
|
||
#define _S_IWRITE 0000200 // write permission, owner
|
||
|
||
_S_IREAD
|
||
Reading only permitted.
|
||
_S_IWRITE
|
||
Writing permitted (effectively permits reading and writing).
|
||
_S_IREAD | _S_IWRITE
|
||
Reading and writing permitted.
|
||
When both constants are given, they are joined with the bitwise-OR operator ( | ).
|
||
In Windows NT, all files are readable, so write-only permission is not available;
|
||
thus the modes _S_IWRITE and _S_IREAD | _S_IWRITE are equivalent.
|
||
|
||
Requirements
|
||
Routine Required header Optional headers Compatibility
|
||
_open <io.h> <fcntl.h>, <sys/types.h>, <sys/stat.h> Win 98, Win Me, Win NT, Win 2000, Win XP
|
||
_wopen <io.h> or <wchar.h> <fcntl.h>, <sys/types.h>, <sys/stat.h> Win NT, Win 2000, Win XP
|
||
|
||
For additional compatibility information, see Compatibility in the Introduction.
|
||
|
||
Libraries
|
||
|
||
All versions of the C run-time libraries.
|
||
|
||
Example
|
||
OPEN.C: This program uses _open to open a file
|
||
named OPEN.C for input and a file named OPEN.OUT
|
||
for output. The files are then closed.
|
||
|
||
#include <fcntl.h>
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
#include <io.h>
|
||
#include <stdio.h>
|
||
|
||
void main( void )
|
||
{
|
||
int fh1, fh2;
|
||
|
||
fh1 = _open( "OPEN.C", _O_RDONLY );
|
||
if( fh1 == -1 )
|
||
perror( "open failed on input file" );
|
||
else
|
||
{
|
||
printf( "open succeeded on input file\n" );
|
||
_close( fh1 );
|
||
}
|
||
|
||
fh2 = _open( "OPEN.OUT", _O_WRONLY | _O_CREAT, _S_IREAD |
|
||
_S_IWRITE );
|
||
if( fh2 == -1 )
|
||
perror( "Open failed on output file" );
|
||
else
|
||
{
|
||
printf( "Open succeeded on output file\n" );
|
||
_close( fh2 );
|
||
}
|
||
}
|
||
|
||
Output
|
||
Open succeeded on input file
|
||
Open succeeded on output file
|
||
|
||
///////////////////////////*/
|
||
|
||
|
||
namespace ZNsConst
|
||
{
|
||
|
||
namespace ZNsCFileMode
|
||
{
|
||
// These values are second parameters of CCFile::Open() function
|
||
|
||
const char* const Read = "r" ;
|
||
const char* const ReadWrite = "r+";
|
||
const char* const RWAppend = "a+";
|
||
const char* const RWCut = "w" ;
|
||
const char* const WriteAppend= "a" ;
|
||
const char* const WriteCut = "w+";
|
||
const char* const Binary = "b" ;
|
||
const char* const WriteBinany= "wb";
|
||
}/*
|
||
namespace ZNsCFileMode*/
|
||
|
||
namespace ZNsCppFileMode
|
||
{
|
||
// These vales are used to be a second parmeter in fstream::open() function
|
||
|
||
const unsigned int Read =std::ios::in ;
|
||
const unsigned int WriteCut =std::ios::out; // == std::ios::out | std::ios::trunc
|
||
const unsigned int Append =std::ios::out | std::ios::app ;
|
||
const unsigned int ReadWrite=std::ios::in | std::ios::out ;
|
||
const unsigned int RWCut =std::ios::in | std::ios::out | std::ios::trunc ;
|
||
|
||
const unsigned int EndPos =std::ios::ate ;
|
||
// std::ios::ate mode move file pointer to file end
|
||
// Use this value with other mode value
|
||
}/*
|
||
namespace ZNsCppFileMode*/
|
||
|
||
namespace ZNsLlioMode // Low Level Input Output
|
||
{
|
||
const unsigned long Read =O_RDONLY;
|
||
const unsigned long Write =O_WRONLY;
|
||
const unsigned long ReadWrite=O_RDWR ;
|
||
const unsigned long RWMake =O_RDWR | O_CREAT ;
|
||
|
||
const unsigned long Append =O_APPEND | O_WRONLY;
|
||
const unsigned long Trunc =O_TRUNC ;
|
||
const unsigned long Create =O_CREAT ;
|
||
const unsigned long OnlyExist =O_EXCL | O_CREAT ;
|
||
const unsigned long WriteMakeCut=O_WRONLY | O_CREAT | O_TRUNC ;
|
||
const unsigned long AppendMake =O_APPEND | O_WRONLY | O_CREAT ;
|
||
|
||
// AppendMake : 덧붙이되 파일이 없으면 새로 만든다.
|
||
// O_EXCL : open only if file doesn't already exist
|
||
// O_EXCL is used with O_CREAT
|
||
}/*
|
||
namespace ZNsLlioMode*/
|
||
|
||
}/*
|
||
namespace ZNsConst*/
|
||
|
||
|
||
/*/////////////////////////
|
||
|
||
struct stat
|
||
{
|
||
_dev_t st_dev;
|
||
_ino_t st_ino;
|
||
unsigned short st_mode;
|
||
short st_nlink;
|
||
short st_uid;
|
||
short st_gid;
|
||
_dev_t st_rdev;
|
||
_off_t st_size;
|
||
time_t st_atime;
|
||
time_t st_mtime;
|
||
time_t st_ctime;
|
||
};
|
||
|
||
/////////////////////////*/
|
||
|
||
|
||
class CFile
|
||
{
|
||
protected:
|
||
FILE* mp_HFile;
|
||
public :
|
||
|
||
CFile()
|
||
{
|
||
mp_HFile=0;
|
||
}/*
|
||
CFile()*/
|
||
|
||
const FILE* GetFilePtr()
|
||
{
|
||
return mp_HFile;
|
||
}/*
|
||
const FILE* GetFilePtr()*/
|
||
|
||
bool Open(const char* APC_FileName, const char* APC_Mode=ZNsConst::ZNsCFileMode::ReadWrite)
|
||
{
|
||
return (mp_HFile=::fopen(APC_FileName, APC_Mode))!=0;
|
||
}/*
|
||
bool Open(const char* APC_FileName,const char* APC_Mode=ZNsConst::ZNsCFileMode::ReadWrite)*/
|
||
|
||
bool Close()
|
||
{
|
||
bool VB_IsOK=(::fclose(mp_HFile)==0); mp_HFile=0; return VB_IsOK;
|
||
}/*
|
||
bool Close()*/
|
||
|
||
size_t Read(void* AP_Buff, size_t AI_BlockSize, size_t AI_BlockCnt)
|
||
{
|
||
return ::fread(AP_Buff, AI_BlockSize, AI_BlockCnt, mp_HFile);
|
||
}/*
|
||
size_t Read(void* AP_Buff, size_t AI_BlockSize, size_t AI_BlockCnt)*/
|
||
|
||
size_t Read(void* AP_ReadBuff, size_t AI_ReadByte)
|
||
{
|
||
return ::fread(AP_ReadBuff, 1, AI_ReadByte, mp_HFile);
|
||
}/*
|
||
size_t Read(void* AP_ReadBuff, size_t AI_ReadByte)*/
|
||
|
||
size_t Write(const void* AP_Buff, size_t AI_BlockSize, size_t AI_BlockCnt)
|
||
{
|
||
return ::fwrite(AP_Buff, AI_BlockSize, AI_BlockCnt, mp_HFile);
|
||
}/*
|
||
size_t Write(const void* AP_Buff, size_t AI_BlockSize, size_t AI_BlockCnt)*/
|
||
|
||
size_t Write(const void* AP_WriteBuff, size_t AI_WriteByte)
|
||
{
|
||
return ::fwrite(AP_WriteBuff, 1, AI_WriteByte, mp_HFile);
|
||
}/*
|
||
size_t Write(const void* AP_WriteBuff, size_t AI_WriteByte)*/
|
||
|
||
size_t Write(const char* AP_Buff)
|
||
{
|
||
return ::fwrite(AP_Buff, 1, strlen(AP_Buff), mp_HFile);
|
||
}/*
|
||
size_t Write(const char* AP_Buff)*/
|
||
|
||
bool Flush() // 파일스트림의 모든 데이타를 즉시 저장한다.
|
||
{
|
||
return ::fflush(mp_HFile)==0;
|
||
}/*
|
||
bool Flush()*/
|
||
|
||
int Seek(long AL_Offset, int AI_Whence=SEEK_SET) // AI_Whence 는 SEEK_SET, SEEK_CUR, SEEK_END 중의 한 값
|
||
{
|
||
return ::fseek(mp_HFile, AL_Offset, AI_Whence);
|
||
}/*
|
||
int Seek(long AL_Offset, int AI_Whence=SEEK_SET)*/
|
||
|
||
long Tell()
|
||
{
|
||
return ::ftell(mp_HFile);
|
||
}/*
|
||
long Tell()*/
|
||
|
||
int GetC()
|
||
{
|
||
return ::fgetc(mp_HFile);
|
||
}/*
|
||
int GetC()*/
|
||
|
||
int PutC(int AI_Char)
|
||
{
|
||
return ::fputc(AI_Char,mp_HFile);
|
||
}/*
|
||
int PutC(int AI_Char)*/
|
||
|
||
int PrintF(const char* APC_Format, ...)
|
||
{
|
||
va_list VP_VarParam; va_start( VP_VarParam, APC_Format);
|
||
|
||
return vfprintf(mp_HFile, APC_Format, VP_VarParam);
|
||
}/*
|
||
int PrintF(const char* APC_Format, ...)*/
|
||
|
||
bool IsError()
|
||
{
|
||
return ::ferror(mp_HFile)!=0;
|
||
}/*
|
||
bool IsError()*/
|
||
|
||
bool IsEOF()
|
||
{
|
||
return ::feof(mp_HFile)!=0;
|
||
}/*
|
||
bool IsEOF()*/
|
||
|
||
public:
|
||
};/*
|
||
class CFile*/
|
||
|
||
|
||
class ZCLLIO // Low Level Input Output
|
||
{
|
||
protected:
|
||
int mi_Handle;
|
||
public :
|
||
|
||
ZCLLIO()
|
||
{
|
||
mi_Handle=-1;
|
||
}/*
|
||
ZCLLIO()*/
|
||
|
||
bool IsValid() const
|
||
{
|
||
return mi_Handle>=0;
|
||
}/*
|
||
bool IsValid() const*/
|
||
|
||
bool Open(ZTypCPCCh APC_Path, int AI_Mode=ZNsConst::ZNsLlioMode::Read, int AI_Perm=0)
|
||
{
|
||
// Mode value is one of many variables in namespace NsCLLio
|
||
// return -1 if it fails;
|
||
|
||
return (mi_Handle= ::open(APC_Path, AI_Mode, AI_Perm)) != -1 ;
|
||
|
||
/*////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ cf)
|
||
fflush() returns 0 if the buffer was successfully flushed.
|
||
The value 0 is also returned in cases
|
||
in which the specified stream has no buffer or is open for reading only.
|
||
A return value of EOF indicates an error.
|
||
Note If fflush returns EOF, data may have been lost due to a write failure.
|
||
When setting up a critical error handler,
|
||
it is safest to turn buffering off with the setvbuf() function
|
||
or to use low-level I/O routines such as _open, _close, and _write instead of the stream I/O functions.
|
||
|
||
■ --
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////////*/
|
||
}/*
|
||
bool Open(ZTypCPCCh APC_Path, int AI_Mode=ZNsConst::ZNsLlioMode::Read, int AI_Perm=0)*/
|
||
|
||
bool OpenRead (ZTypCPCCh APC_Path , int AI_Perm=0) // 읽기
|
||
{ return (mi_Handle= ::open( APC_Path , ZNsConst::ZNsLlioMode::Read , AI_Perm)) != -1 ; }
|
||
bool OpenWrite(ZTypCPCCh APC_Path , int AI_Perm=0) // 쓰기
|
||
{ return (mi_Handle= ::open( APC_Path , ZNsConst::ZNsLlioMode::Write , AI_Perm)) != -1 ; }
|
||
bool OpenRW (ZTypCPCCh APC_Path , int AI_Perm=0) // 읽기/쓰기
|
||
{ return (mi_Handle= ::open( APC_Path , ZNsConst::ZNsLlioMode::ReadWrite, AI_Perm)) != -1 ; }
|
||
bool OpenApp (ZTypCPCCh APC_Path , int AI_Perm=0) // 덧붙이기
|
||
{ return (mi_Handle= ::open( APC_Path , ZNsConst::ZNsLlioMode::Append , AI_Perm)) != -1 ; }
|
||
|
||
|
||
#ifndef S_IRWXU
|
||
#define S_IRWXU 0
|
||
#endif
|
||
#ifndef S_IRUSR
|
||
#define S_IRUSR 0
|
||
#endif
|
||
#ifndef S_IWUSR
|
||
#define S_IWUSR 0
|
||
#endif
|
||
#ifndef S_IXUSR
|
||
#define S_IXUSR 0
|
||
#endif
|
||
|
||
#ifndef S_IRWXG
|
||
#define S_IRWXG 0
|
||
#endif
|
||
#ifndef S_IRGRP
|
||
#define S_IRGRP 0
|
||
#endif
|
||
#ifndef S_IWGRP
|
||
#define S_IWGRP 0
|
||
#endif
|
||
#ifndef S_IXGRP
|
||
#define S_IXGRP 0
|
||
#endif
|
||
|
||
#ifndef S_IRWXO
|
||
#define S_IRWXO 0
|
||
#endif
|
||
#ifndef S_IROTH
|
||
#define S_IROTH 0
|
||
#endif
|
||
#ifndef S_IWOTH
|
||
#define S_IWOTH 0
|
||
#endif
|
||
#ifndef S_IXOTH
|
||
#define S_IXOTH 0
|
||
#endif
|
||
|
||
/*##############################################################################
|
||
|
||
□ unix open 함수의 주요 상수.
|
||
|
||
S_IRWXU 00700 user (file owner) has read, write and execute permission
|
||
S_IRUSR 00400 user has read permission
|
||
S_IWUSR 00200 user has write permission
|
||
S_IXUSR 00100 user has execute permission
|
||
|
||
S_IRWXG 00070 group has read, write and execute permission
|
||
S_IRGRP 00040 group has read permission
|
||
S_IWGRP 00020 group has write permission
|
||
S_IXGRP 00010 group has execute permission
|
||
|
||
S_IRWXO 00007 others have read, write and execute permission
|
||
S_IROTH 00004 others have read permission
|
||
S_IWOTH 00002 others have write permission
|
||
S_IXOTH 00001 others have execute permission
|
||
|
||
##############################################################################*/
|
||
|
||
bool MakeCut(ZTypCPCCh APC_Path, int AI_Perm=(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))
|
||
{ return Open(APC_Path, ZNsConst::ZNsLlioMode::WriteMakeCut, AI_Perm); }
|
||
bool MakeRW (ZTypCPCCh APC_Path, int AI_Perm=(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))
|
||
{ return Open(APC_Path, ZNsConst::ZNsLlioMode::RWMake , AI_Perm); }
|
||
bool MakeApp(ZTypCPCCh APC_Path, int AI_Perm=(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))
|
||
{ return Open(APC_Path, ZNsConst::ZNsLlioMode::AppendMake , AI_Perm); } // 덧붙이되 없으면 새로 만듦.
|
||
|
||
inline int GetHandle() const
|
||
{
|
||
return mi_Handle;
|
||
}/*
|
||
inline int GetHandle() const*/
|
||
|
||
off_t GetFileSize()
|
||
{
|
||
// typedef long _off_t; IN Windows
|
||
// typedef long off_t; IN Linux
|
||
|
||
struct stat VO_FileStatus;
|
||
|
||
if(fstat(mi_Handle, &VO_FileStatus)<0)
|
||
{ return -1; }
|
||
|
||
return VO_FileStatus.st_size;
|
||
}/*
|
||
off_t GetFileSize()*/
|
||
|
||
size_t Read(void* AP_Buffer, size_t AI_ByteSize)
|
||
{
|
||
return read(mi_Handle,AP_Buffer,AI_ByteSize);
|
||
|
||
// typedef unsigned int size_t;
|
||
}/*
|
||
size_t Read(void* AP_Buffer, size_t AI_ByteSize)*/
|
||
|
||
size_t Write(const void* AP_Buffer, size_t AI_ByteSize)
|
||
{
|
||
// _CRTIMP int __cdecl write(int, const void *, unsigned int); // In Visual C++ 6.0
|
||
|
||
return write(mi_Handle,AP_Buffer,AI_ByteSize);
|
||
}/*
|
||
size_t Write(const void* AP_Buffer, size_t AI_ByteSize)*/
|
||
|
||
off_t Seek(off_t AI_Offset,int AI_Whence=SEEK_SET) const
|
||
{
|
||
// typedef long off_t;
|
||
// AI_Whence is one of SEEK_SET, SEEK_CUR, SEEK_END
|
||
|
||
return ::lseek(mi_Handle,AI_Offset,AI_Whence);
|
||
|
||
/* MSDN : _lseek() returns the offset, in bytes, of the new position from the beginning of the file.
|
||
_lseeki64 returns the offset in a 64-bit integer.
|
||
The function returns ?1L to indicate an error
|
||
and sets errno either to EBADF, meaning the file handle is invalid,
|
||
or to EINVAL, meaning the value for origin is invalid or the position specified by offset
|
||
is before the beginning of the file.
|
||
On devices incapable of seeking (such as terminals and printers),
|
||
the return value is undefined. */
|
||
}/*
|
||
off_t Seek(off_t AI_Offset,int AI_Whence=SEEK_SET) const*/
|
||
|
||
|
||
/*//////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ int _fstat ( int handle, struct _stat *buffer );
|
||
__int64 _fstati64( int handle, struct _stat *buffer );
|
||
|
||
Function Required Header Compatibility
|
||
_fstat <sys/stat.h> and <sys/types.h> Win 95, Win NT
|
||
_fstati64 <sys/stat.h> and <sys/types.h> Win 95, Win NT
|
||
|
||
Return Value
|
||
|
||
_fstat and _fstati64 return 0 if the file-status information is obtained.
|
||
A return value of ?1 indicates an error, in which case errno is set to EBADF,
|
||
indicating an invalid file handle.
|
||
|
||
When you declear struct stat even in a C++ file, To use struct keyword is better
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
bool GetFStat(struct stat& ARR_StatBuf)
|
||
{
|
||
return fstat(mi_Handle, &ARR_StatBuf)==0;
|
||
}/*
|
||
bool GetFStat(struct stat& ARR_StatBuf)*/
|
||
|
||
static bool GetFStat(ZTypCPCCh APC_Path, struct stat& ARR_StatBuf)
|
||
{
|
||
return stat(APC_Path, &ARR_StatBuf)==0;
|
||
}/*
|
||
static bool GetFStat(ZTypCPCCh APC_Path, struct stat& ARR_StatBuf)*/
|
||
|
||
|
||
#if !defined(_WIN)
|
||
|
||
|
||
static bool GetLStat(ZTypCPCCh APC_Path, struct stat& ARR_StatBuf)
|
||
{
|
||
return lstat(APC_Path, &ARR_StatBuf)==0;
|
||
|
||
// lstat() return information of link itself if Path is a link
|
||
}/*
|
||
static bool GetLStat(ZTypCPCCh Path, struct stat& ARR_StatBuf)*/
|
||
|
||
/*/////////////////////////////////////////
|
||
|
||
#define S_ISBLK(m) (((m)&_IFMT) == _IFBLK)
|
||
#define S_ISCHR(m) (((m)&_IFMT) == _IFCHR)
|
||
#define S_ISDIR(m) (((m)&_IFMT) == _IFDIR)
|
||
#define S_ISFIFO(m) (((m)&_IFMT) == _IFIFO)
|
||
#define S_ISREG(m) (((m)&_IFMT) == _IFREG)
|
||
#define S_ISLNK(m) (((m)&_IFMT) == _IFLNK)
|
||
#define S_ISSOCK(m) (((m)&_IFMT) == _IFSOCK)
|
||
|
||
/////////////////////////////////////////*/
|
||
|
||
|
||
#endif //!defined(_WIN)
|
||
|
||
|
||
bool Close()
|
||
{
|
||
if(mi_Handle<0) return true;
|
||
|
||
bool VB_Result=(::close(mi_Handle)==0);
|
||
|
||
mi_Handle = -1; return VB_Result;
|
||
|
||
// close() returns -1 if it fail
|
||
// close() returns 0 if it succeed
|
||
}/*
|
||
bool Close()*/
|
||
|
||
int SetDefaultMask(int AI_Mode)
|
||
{
|
||
/*///////////////////////////////////
|
||
|
||
int _umask(
|
||
int pmode
|
||
);
|
||
|
||
Sets the default file-permission mask.
|
||
|
||
Parameter
|
||
pmode
|
||
Default permission setting.
|
||
Return Value
|
||
_umask returns the previous value of pmode. There is no error return.
|
||
|
||
///////////////////////////////////*/
|
||
|
||
return umask(AI_Mode);
|
||
}/*
|
||
int SetDefaultMask(int AI_Mode)*/
|
||
|
||
public:
|
||
};/*
|
||
class ZCLLIO*/
|
||
|
||
|
||
//////////////// class ZCFileInfo ////////////////
|
||
|
||
|
||
class ZCFileInfo
|
||
{
|
||
protected:
|
||
struct stat mo_FileStatus;
|
||
public :
|
||
|
||
bool GetStatus(ZTypCPCCh AP_File)
|
||
{
|
||
return stat(AP_File, &mo_FileStatus) != -1 ;
|
||
|
||
/* Each of these functions returns 0 if the file-status information is obtained.
|
||
A return value of ?1 indicates an error,
|
||
in which case errno is set to ENOENT,
|
||
indicating that the filename or path could not be found. */
|
||
}/*
|
||
bool GetStatus(ZTypCPCCh APC_Path)*/
|
||
|
||
bool GetStatus(int AI_FileHandle)
|
||
{
|
||
return fstat(AI_FileHandle, &mo_FileStatus) != -1;
|
||
}/*
|
||
bool GetStatus(int AI_FileHandle)*/
|
||
|
||
struct stat& GetStatusObj(){ return mo_FileStatus; }
|
||
|
||
public:
|
||
};/*
|
||
class ZCFileInfo*/
|
||
|
||
|
||
/*////////////////////////////////////////////////////////////////////////////
|
||
|
||
_fstat, _fstati64
|
||
Get information about an open file.
|
||
|
||
int _fstat( int handle, struct _stat *buffer );
|
||
|
||
__int64 _fstati64( int handle, struct _stat *buffer );
|
||
|
||
Function Required Header Compatibility
|
||
_fstat <sys/stat.h> and <sys/types.h> Win 95, Win NT
|
||
_fstati64 <sys/stat.h> and <sys/types.h> Win 95, Win NT
|
||
|
||
For additional compatibility information, see Compatibility in the Introduction.
|
||
|
||
Libraries
|
||
|
||
LIBC.LIB Single thread static library, retail version
|
||
LIBCMT.LIB Multithread static library, retail version
|
||
MSVCRT.LIB Import library for MSVCRT.DLL, retail version
|
||
|
||
Return Value
|
||
|
||
_fstat and _fstati64 return 0 if the file-status information is obtained.
|
||
A return value of ?1 indicates an error, in which case errno is set to EBADF,
|
||
indicating an invalid file handle.
|
||
|
||
Parameters
|
||
|
||
handle
|
||
Handle of open file
|
||
buffer
|
||
Pointer to structure to store results
|
||
|
||
Remarks
|
||
|
||
The _fstat function obtains information about the open file associated with handle and
|
||
stores it in the structure pointed to by buffer.
|
||
The _stat structure, defined in SYS\STAT.H, contains the following fields:
|
||
|
||
// typedef long time_t;
|
||
|
||
st_atime
|
||
Time of last file access.
|
||
|
||
st_ctime
|
||
Time of creation of file.
|
||
|
||
st_dev
|
||
If a device, handle; otherwise 0.
|
||
|
||
st_mode
|
||
Bit mask for file-mode information. The _S_IFCHR bit is set if handle refers to a device. The _S_IFREG bit is set if handle refers to an ordinary file. The read/write bits are set according to the file’s permission mode. _S_IFCHR and other constants are defined in SYS\STAT.H.
|
||
|
||
st_mtime
|
||
Time of last modification of file.
|
||
|
||
st_nlink
|
||
Always 1 on non-NTFS file systems.
|
||
|
||
st_rdev
|
||
If a device, handle; otherwise 0.
|
||
|
||
st_size
|
||
Size of the file in bytes.
|
||
|
||
If handle refers to a device, the st_atime,
|
||
st_ctime, and st_mtime and st_size fields are not meaningful.
|
||
|
||
Because STAT.H uses the _dev_t type, which is defined in TYPES.H,
|
||
you must include TYPES.H before STAT.H in your code.
|
||
|
||
Example
|
||
|
||
FSTAT.C: This program uses _fstat to report
|
||
the size of a file named F_STAT.OUT.
|
||
|
||
#include <io.h>
|
||
#include <fcntl.h>
|
||
#include <time.h>
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
void main( void )
|
||
{
|
||
struct _stat iov_base;
|
||
int fh, result;
|
||
char buffer[] = "A line to output";
|
||
|
||
if( (fh = _open( "f_stat.out", _O_CREAT | _O_WRONLY |
|
||
_O_TRUNC )) == -1 )
|
||
_write( fh, buffer, strlen( buffer ) );
|
||
|
||
// Get data associated with "fh":
|
||
result = _fstat( fh, &iov_base );
|
||
|
||
// Check if statistics are valid:
|
||
|
||
if( result != 0 )
|
||
{
|
||
printf( "Bad file handle\n" );
|
||
}
|
||
else
|
||
{
|
||
printf( "File size : %ld\n", iov_base.st_size );
|
||
printf( "Time modified : %s", ctime( &iov_base.st_ctime ) );
|
||
}
|
||
|
||
_close( fh );
|
||
}
|
||
|
||
Output
|
||
|
||
File size : 0
|
||
Time modified : Tue Mar 21 15:23:08 1995
|
||
|
||
/////////////////////////////////////////////////////////////////*/
|
||
|
||
/*/////////////////////////////////////////////////////////////////
|
||
|
||
#define _S_IREAD 0000400 // read permission, owner
|
||
#define _S_IWRITE 0000200 // write permission, owner
|
||
|
||
#define _S_IFMT 0170000 // file type mask
|
||
#define _S_IFDIR 0040000 // directory
|
||
#define _S_IFCHR 0020000 // character special
|
||
#define _S_IFIFO 0010000 // pipe
|
||
#define _S_IFREG 0100000 // regular
|
||
#define _S_IEXEC 0000100 // execute/search permission, owner
|
||
|
||
#define S_IFMT _S_IFMT
|
||
#define S_IFDIR _S_IFDIR
|
||
#define S_IFCHR _S_IFCHR
|
||
#define S_IFREG _S_IFREG
|
||
|
||
/////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
namespace ZNsFileStatMode
|
||
{
|
||
#ifndef S_IFIFO
|
||
#define S_IFIFO _S_IFIFO
|
||
#endif
|
||
const unsigned int File =S_IFMT ;
|
||
const unsigned int Directory =S_IFDIR;
|
||
const unsigned int CharDevice =S_IFCHR;
|
||
const unsigned int DefaultFile=S_IFREG;
|
||
const unsigned int Fifo =S_IFIFO;
|
||
//const unsigned int Execute =S_IEXEC;
|
||
}/*
|
||
namespace ZNsFileStatMode*/
|
||
|
||
|
||
/*////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ WIN32_FIND_DATA
|
||
|
||
typedef struct _WIN32_FIND_DATAA {
|
||
DWORD dwFileAttributes;
|
||
FILETIME ftCreationTime;
|
||
FILETIME ftLastAccessTime;
|
||
FILETIME ftLastWriteTime;
|
||
DWORD nFileSizeHigh;
|
||
DWORD nFileSizeLow;
|
||
DWORD dwReserved0;
|
||
DWORD dwReserved1;
|
||
_Field_z_ CHAR cFileName[ MAX_PATH ];
|
||
_Field_z_ CHAR cAlternateFileName[ 14 ];
|
||
#ifdef _MAC
|
||
DWORD dwFileType;
|
||
DWORD dwCreatorType;
|
||
WORD wFinderFlags;
|
||
#endif
|
||
} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
|
||
typedef struct _WIN32_FIND_DATAW {
|
||
DWORD dwFileAttributes;
|
||
FILETIME ftCreationTime;
|
||
FILETIME ftLastAccessTime;
|
||
FILETIME ftLastWriteTime;
|
||
DWORD nFileSizeHigh;
|
||
DWORD nFileSizeLow;
|
||
DWORD dwReserved0;
|
||
DWORD dwReserved1;
|
||
_Field_z_ WCHAR cFileName[ MAX_PATH ];
|
||
_Field_z_ WCHAR cAlternateFileName[ 14 ];
|
||
#ifdef _MAC
|
||
DWORD dwFileType;
|
||
DWORD dwCreatorType;
|
||
WORD wFinderFlags;
|
||
#endif
|
||
} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW;
|
||
#ifdef UNICODE
|
||
typedef WIN32_FIND_DATAW WIN32_FIND_DATA;
|
||
typedef PWIN32_FIND_DATAW PWIN32_FIND_DATA;
|
||
typedef LPWIN32_FIND_DATAW LPWIN32_FIND_DATA;
|
||
#else
|
||
typedef WIN32_FIND_DATAA WIN32_FIND_DATA;
|
||
typedef PWIN32_FIND_DATAA PWIN32_FIND_DATA;
|
||
typedef LPWIN32_FIND_DATAA LPWIN32_FIND_DATA;
|
||
#endif // UNICODE
|
||
|
||
|
||
typedef struct _WIN32_FIND_DATA
|
||
{
|
||
DWORD dwFileAttributes;
|
||
FILETIME ftCreationTime;
|
||
FILETIME ftLastAccessTime;
|
||
FILETIME ftLastWriteTime;
|
||
DWORD nFileSizeHigh;
|
||
DWORD nFileSizeLow;
|
||
DWORD dwOID;
|
||
TCHAR cFileName[MAX_PATH];
|
||
} WIN32_FIND_DATA;
|
||
|
||
Members
|
||
dwFileAttributes
|
||
|
||
File attributes of the file found.
|
||
The following table shows the possible values for dwFileAttribute. Value Description
|
||
|
||
FILE_ATTRIBUTE_ARCHIVE
|
||
Indicates that the file or directory is an archive file or directory.
|
||
Applications use this attribute to mark files for backup or removal.
|
||
FILE_ATTRIBUTE_COMPRESSED
|
||
Indicates that the file or directory is compressed.
|
||
For a file, this means that all of the data in the file is compressed.
|
||
For a directory, this means that compression is the default
|
||
for newly created files and subdirectories.
|
||
FILE_ATTRIBUTE_DIRECTORY
|
||
Indicates that the handle identifies a directory.
|
||
FILE_ATTRIBUTE_ENCRYPTED
|
||
Indicates that the file or directory is encrypted.
|
||
For a file, this means that all data streams are encrypted. For a directory, this means that encryption is the default for newly created files and subdirectories.
|
||
FILE_ATTRIBUTE_HIDDEN
|
||
Indicates that the file or directory is hidden.
|
||
It is not included in an ordinary directory listing.
|
||
FILE_ATTRIBUTE_INROM
|
||
Indicates that this file is an operating system file stored in ROM.
|
||
These files are read-only; they cannot be modified.
|
||
FILE_ATTRIBUTE_NORMAL
|
||
Indicates that the file or directory has no other attributes set.
|
||
This attribute is valid only if used alone.
|
||
FILE_ATTRIBUTE_READONLY
|
||
Indicates that the file or directory is read-only.
|
||
Applications can read the file but cannot write to it or delete it.
|
||
In the case of a directory, applications cannot delete it.
|
||
FILE_ATTRIBUTE_REPARSE_POINT
|
||
Indicates that the file has an associated reparse point.
|
||
FILE_ATTRIBUTE_ROMMODULE
|
||
Indicates that this file is an operating system file stored in ROM and executed directly from ROM,
|
||
rather than being first copied to RAM.
|
||
The CreateFile function cannot be used to access this file,
|
||
instead the LoadLibrary and CreateProcess functions must be used.
|
||
FILE_ATTRIBUTE_ROMSTATICREF
|
||
Indicates that the file is a DLL module that has an implicit reference
|
||
from at least one other file that is in the modules section of the image.
|
||
A file having this attribute cannot replace the functionality of the DLL with a RAM copy of the same DLL.
|
||
A file having this attribute must also have the FILE_ATTRIBUTE_INROM and FILE_ATTRIBUTE_ROMMODULE attributes.
|
||
FILE_ATTRIBUTE_SPARSE_FILE
|
||
Indicates that the file is a sparse file.
|
||
FILE_ATTRIBUTE_SYSTEM
|
||
Indicates that the file or directory is part of the operating system
|
||
or is used exclusively by the operating system.
|
||
FILE_ATTRIBUTE_TEMPORARY
|
||
Indicates that the file is being used for temporary storage.
|
||
File systems attempt to keep all of the data in memory for quicker access,
|
||
rather than flushing it back to mass storage.
|
||
A temporary file should be deleted by the application as soon as it is no longer needed.
|
||
|
||
ftCreationTime
|
||
FILETIME structure containing the time the file was created.
|
||
FindFirstFile and FindNextFile report file times in Coordinated Universal Time (UTC) format.
|
||
These functions set the FILETIME members to zero
|
||
if the file system containing the file does not support this time member.
|
||
You can use the FileTimeToLocalFileTime function to convert from UTC to local time,
|
||
and then use the FileTimeToSystemTime function
|
||
to convert the local time to a SYSTEMTIME structure containing individual members
|
||
for the month, day, year, weekday, hour, minute, second, and millisecond.
|
||
ftLastAccessTime
|
||
FILETIME structure containing the time that the file was last accessed.
|
||
The time is in UTC format; the FILETIME members are zero
|
||
if the file system does not support this time member.
|
||
ftLastWriteTime
|
||
FILETIME structure containing the time that the file was last written to.
|
||
The time is in UTC format; the FILETIME members are zero
|
||
if the file system does not support this time member.
|
||
nFileSizeHigh
|
||
High-order DWORD value of the file size, in bytes.
|
||
This value is zero unless the file size is greater than MAXDWORD.
|
||
The size of the file is equal to (nFileSizeHigh * MAXDWORD) + nFileSizeLow.
|
||
nFileSizeLow
|
||
Low-order DWORD value of the file size, in bytes.
|
||
dwOID
|
||
Object identifier of the file.
|
||
cFileName
|
||
Null-terminated string that is the name of the file.
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
#ifndef MAX_PATH
|
||
#define MAX_PATH 512*2
|
||
#endif
|
||
|
||
#define _MAX_PATH2 MAX_PATH*3
|
||
|
||
#ifdef _WIN
|
||
typedef HANDLE TypeDirID;
|
||
#elif defined(__unix__)
|
||
typedef DIR* TypeDirID;
|
||
#else
|
||
typedef DIR* TypeDirID;
|
||
#endif
|
||
|
||
|
||
#if defined(_WIN)
|
||
|
||
class ZCFileData : public WIN32_FIND_DATAA
|
||
{
|
||
public:
|
||
|
||
bool IsDir() const
|
||
{
|
||
return (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==FILE_ATTRIBUTE_DIRECTORY;
|
||
|
||
// #define FILE_ATTRIBUTE_DIRECTORY 0x00000010
|
||
}/*
|
||
bool IsDir() const*/
|
||
|
||
ZTypCPCh GetFileName() const
|
||
{
|
||
return this->cFileName;
|
||
}/*
|
||
ZTypCPCh GetFileName() const*/
|
||
|
||
public:
|
||
};/*
|
||
class ZCFileData*/
|
||
|
||
#else //!defined(_WIN)
|
||
|
||
class ZCFileData : public stat
|
||
{
|
||
public:
|
||
|
||
char cFileName[_MAX_PATH2];
|
||
|
||
inline bool IsDir() const
|
||
{ return S_ISDIR(this->st_mode); }
|
||
|
||
inline ZTypCPChar GetFileName() const
|
||
{ return cFileName ; }
|
||
|
||
public:
|
||
};/*
|
||
class ZCFileData*/
|
||
|
||
|
||
#endif //!defined(_WIN)
|
||
|
||
|
||
/*//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
HANDLE FindFirstFile(LPCTSTR lpFileName, LPWIN32_FIND_DATA lpFindFileData);
|
||
|
||
#define MAX_PATH 260
|
||
|
||
Parameters
|
||
lpFileName
|
||
[in] Pointer to a null-terminated string that specifies a valid directory or path and file name,
|
||
which can contain wildcard characters (* and ?).
|
||
If the string ends with a wildcard, a period, or a directory name,
|
||
the user must have access to the root and all subdirectories on the path.
|
||
In the ANSI version of this function, the name is limited to MAX_PATH characters.
|
||
To extend this limit to 32,767 wide characters,
|
||
call the Unicode version of the function and prepend "\\?\" to the path.
|
||
For more information, see Naming a File.
|
||
|
||
Windows Me/98/95: This string must not exceed MAX_PATH characters.
|
||
|
||
lpFindFileData
|
||
[out] Pointer to the WIN32_FIND_DATA structure that receives information about the found file or subdirectory.
|
||
|
||
Return Values
|
||
If the function succeeds,
|
||
the return value is a search handle used in a subsequent call to FindNextFile or FindClose.
|
||
If the function fails,
|
||
the return value is INVALID_HANDLE_VALUE.
|
||
To get extended error information, call GetLastError.
|
||
|
||
Remarks
|
||
The FindFirstFile function opens a search handle
|
||
and returns information about the first file whose name matches the specified pattern.
|
||
It searches both the long and short file names.
|
||
After the search handle has been established,
|
||
use the FindNextFile function to search for other files that match the same pattern.
|
||
When the search handle is no longer needed, close it by using the FindClose function.
|
||
|
||
In rare cases,
|
||
file attribute information on NTFS file systems may not be current at the time you call this function.
|
||
To obtain the current NTFS file attributes, call GetFileInformationByHandle.
|
||
|
||
This function searches for files by name only;
|
||
it cannot be used for attribute-based searches.
|
||
You cannot use root directories as the lpFileName input string for FindFirstFile,
|
||
with or without a trailing backslash.
|
||
To examine files in a root directory,
|
||
use something like "C:\*" and step through the directory with FindNextFile.
|
||
To get the attributes of a root directory, use GetFileAttributes.
|
||
Prepending the string "\\?\" does not allow access to the root directory.
|
||
|
||
Similarly, on network shares, you can use an lpFileName of the form "\\server\service\*"
|
||
but you cannot use an lpFileName that points to the share itself, such as "\\server\service".
|
||
|
||
To examine any directory other than a root directory,
|
||
use an appropriate path to that directory, with no trailing backslash.
|
||
For example, an argument of "C:\windows" will return information about the directory "C:\windows",
|
||
not about any directory or file in "C:\windows".
|
||
An attempt to open a search with a trailing backslash will always fail.
|
||
|
||
trail [treil] 【L 「(배를) 끌다」의 뜻에서】 n.
|
||
1 a 끌고 간 자국, 지나간 자국, 흔적; 선적(船跡), 항적(航跡)
|
||
the ~ of a slug 달팽이의 지나간 자국
|
||
hot[hard] on the ~ (of ···) (···의) 바로 뒤에
|
||
b 냄새 자국 ((짐승의)), 실마리, 단서 ((수사상의))
|
||
2 《미캐나다》 (황야 등의) 밟아 다져진 길, (산속의) 작은 길, 오솔길, 산길
|
||
3 꼬리 ((유성의)); 길게 늘어진 자락 ((구름연기 등의)); 긴 옷자락; 늘어진 술머리카락 ((등)); (사람차 등의) 줄, 열; (땅을) 기는 덩굴[가지]; 예망(曳網)(=~ net)
|
||
4 【군사】 세워총(의 자세)
|
||
5 (사고재해 등의) 결과, 여파, 후유증
|
||
at the ~ 【군사】 세워총의 자세로
|
||
blaze a ~ to ···을 개척하다, 창시하다(pioneer)
|
||
hit the ~ 《속어》 여행 떠나다; 가버리다, 떠나다
|
||
off the ~ (짐승의) 냄새 자국을 잃고; 실마리를 잃고
|
||
on the ~ (of) ···을 추적하여; 냄새 자국[실마리]을 찾아내어
|
||
vt.
|
||
1 끌다; <옷자락 등을> 질질 끌다, 끌며 가다; <그물 등을> 끌다
|
||
~ one's skirt 치마를 질질 끌다
|
||
《~+목+전+명》 ~ a toy cart by[on] a piece of string 장난감 수레를 끈으로 끌다
|
||
《~+목+부》 He ~ed along his wounded leg. 그는 다친 다리를 끌며 걸었다
|
||
2 <구름연기 등을> 길게 나부끼게 하다; <노를> 젓지 않고 놓아 두다
|
||
3 <사람동물 등을> 추적하다, 미행하다
|
||
《~+목+전+명》 ~ a person to his house 집까지 ···을 뒤쫓다
|
||
4 《미구어》 (경주 등에서) ···의 뒤를 달리다; <가축을> 뒤쫓다; (긴 열을 지어) 뒤에 붙어서 가다; (시합에서) 지고 있다
|
||
5 《미》 <풀 등을> 밟아 길을 내다
|
||
6 <이야기 등을> 질질 끌다; 길게 발음하다
|
||
7 【군사】 세워총을 하다
|
||
T~ arms! 세워총!
|
||
~ one's coat 일부러 반발을 유발하다; 싸움을 걸다
|
||
vi.
|
||
1 끌다; <옷자락 등이> 질질 끌리다, <머리카락 등이> 늘어지다
|
||
《~+전+명》 Her long bridal gown was ~ing on[over] the church floor. 그녀의 긴 신부 의상이 교회의 마루에 질질 끌리고 있었다
|
||
2 <덩굴이> 기다
|
||
《~+전+명》 Ivy ~s over the house. 담쟁이덩굴이 집에 기어 오르고 있다
|
||
3 <구름연기가> 길게 나부끼다
|
||
《~+전+명》 Smoke ~ed from the chimney. 연기가 굴뚝에서 길게 나부꼈다
|
||
4 발을 질질 끌며 걷다 ((along)), 힘없이[느릿느릿] 걷다, 낙오하다
|
||
5 <소리가> 점점 사라지다[약해지다] ((off, away))
|
||
《~+부》 《~+전+명》 Her voice ~ed off[wy] into silence. 그녀의 목소리는 서서히 사라져 갔다
|
||
6 <이야기 등이> 질질 계속되다 ((on))
|
||
7 마지막으로 도착하다 ((in))
|
||
~ on <싫은 시간행사 등이> 길어지다( vi. 6)
|
||
|
||
BOOL RemoveDirectory(LPCTSTR lpPathName);
|
||
|
||
Parameters
|
||
lpPathName
|
||
[in] Pointer to a null-terminated string that specifies the path of the directory to be removed.
|
||
The path must specify an empty directory,
|
||
and the calling process must have delete access to the directory.
|
||
In the ANSI version of this function, the name is limited to MAX_PATH characters.
|
||
To extend this limit to 32,767 wide characters,
|
||
call the Unicode version of the function and prepend "\\?\" to the path.
|
||
For more information, see Naming a File.
|
||
|
||
Windows Me/98/95: This string must not exceed MAX_PATH characters.
|
||
|
||
Return Values
|
||
If the function succeeds, the return value is nonzero.
|
||
If the function fails, the return value is zero. To get extended error information, call GetLastError.
|
||
|
||
BOOL DeleteFile( LPCTSTR lpFileName );
|
||
|
||
Parameters
|
||
lpFileName
|
||
[in] Pointer to a null-terminated string that specifies the file to be deleted.
|
||
In the ANSI version of this function, the name is limited to MAX_PATH characters.
|
||
To extend this limit to 32,767 wide characters,
|
||
call the Unicode version of the function and prepend "\\?\" to the path.
|
||
For more information, see Naming a File.
|
||
|
||
Windows Me/98/95: This string must not exceed MAX_PATH characters.
|
||
|
||
Return Values
|
||
If the function succeeds, the return value is nonzero.
|
||
If the function fails, the return value is zero.
|
||
To get extended error information, call GetLastError.
|
||
|
||
int _rmdir (const char *dirname );
|
||
int _wrmdir (const wchar_t *dirname );
|
||
|
||
Parameters
|
||
dirname
|
||
Path of directory to be removed.
|
||
Return Value
|
||
Each of these functions returns 0
|
||
if the directory is successfully deleted.
|
||
A return value of ?1 indicates an error, and errno is set to one of the following values:
|
||
|
||
ENOTEMPTY
|
||
Given path is not a directory; directory is not empty;
|
||
or directory is either current working directory or root directory.
|
||
ENOENT
|
||
Path is invalid.
|
||
EACCESS
|
||
A program has an open handle to the directory.
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
namespace ZNsIFace
|
||
{
|
||
|
||
class ZCViewDir
|
||
{
|
||
private:
|
||
int mi_Depth;
|
||
private:
|
||
|
||
void PrintDepth()
|
||
{
|
||
for(int i=1; i<=mi_Depth; ++i) ::printf(" ");
|
||
}/*
|
||
void PrintDepth()*/
|
||
|
||
/*private:*/
|
||
public :
|
||
|
||
ZCViewDir()
|
||
{
|
||
mi_Depth=0;
|
||
}/*
|
||
ZCViewDir()*/
|
||
|
||
ZNsMain::ZNsEnum::ZERun OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)
|
||
{
|
||
printf("◇ "); PrintDepth();
|
||
printf("OnFile:APC_NowPath=\"%s\", File=\"%s\"\n", APC_NowPath, AR_CFileData.GetFileName());
|
||
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
ZNsMain::ZNsEnum::ZERun OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)*/
|
||
|
||
ZNsMain::ZNsEnum::ZERun OnDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)
|
||
{
|
||
printf("◆ OnDir:Dir=\"%s\"\n", AR_CFileData.GetFileName()); return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
ZNsMain::ZNsEnum::ZERun OnDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)*/
|
||
|
||
|
||
template<typename TTypeHelp> ZNsMain::ZNsEnum::ZERun
|
||
OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp)
|
||
{
|
||
printf("◇ "); PrintDepth();
|
||
printf("OnFile:APC_NowPath=\"%s\", File=\"%s\"\n", APC_NowPath, AR_CFileData.GetFileName());
|
||
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TTypeHelp> ZNsMain::ZNsEnum::ZERun
|
||
OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp) */
|
||
|
||
template<typename TTypeHelp> ZNsMain::ZNsEnum::ZERun
|
||
OnDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp)
|
||
{
|
||
printf("◆ OnDir:Dir=\"%s\"\n", AR_CFileData.GetFileName()); return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TTypeHelp> ZNsMain::ZNsEnum::ZERun
|
||
OnDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp) */
|
||
|
||
ZNsMain::ZNsEnum::ZERun OnIntoDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)
|
||
{
|
||
printf("▶ "); PrintDepth();
|
||
printf("OnIntoDir:APC_NowPath=\"%s\", cFileName=\"%s\"\n", APC_NowPath, AR_CFileData.GetFileName());
|
||
|
||
++mi_Depth; return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
ZNsMain::ZNsEnum::ZERun OnIntoDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)*/
|
||
|
||
ZNsMain::ZNsEnum::ZERun OnOutOfDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)
|
||
{
|
||
--mi_Depth;
|
||
|
||
printf("◀ "); PrintDepth();
|
||
printf("OnOutOfDir:APC_NowPath=\"%s\", cFileName=\"%s\"\n", APC_NowPath, AR_CFileData.GetFileName());
|
||
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
ZNsMain::ZNsEnum::ZERun OnOutOfDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)*/
|
||
|
||
|
||
template<typename TTypeHelp> ZNsMain::ZNsEnum::ZERun OnIntoDir(
|
||
ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp )
|
||
{
|
||
printf("▶ "); PrintDepth();
|
||
printf("OnIntoDir:APC_NowPath=\"%s\", cFileName=\"%s\"\n", APC_NowPath,AR_CFileData.GetFileName());
|
||
|
||
++mi_Depth; return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TTypeHelp> ZNsMain::ZNsEnum::ZERun OnIntoDir
|
||
(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp) */
|
||
|
||
template<typename TTypeHelp> ZNsMain::ZNsEnum::ZERun OnOutOfDir(
|
||
ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp)
|
||
{
|
||
--mi_Depth;
|
||
|
||
printf("◀ "); PrintDepth();
|
||
printf("OnOutOfDir:APC_NowPath=\"%s\", cFileName=\"%s\"\n", APC_NowPath, AR_CFileData.GetFileName());
|
||
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TTypeHelp> ZNsMain::ZNsEnum::ZERun OnOutOfDir(
|
||
ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp) */
|
||
|
||
public:
|
||
};/*
|
||
class ZCViewDir*/
|
||
|
||
|
||
class ZCViewDirOfFileList
|
||
{
|
||
public :
|
||
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileDataList)
|
||
{
|
||
ARR_CFileDataList.push_back(AR_CFileData); return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileDataList) */
|
||
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnIntoDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileDataList)
|
||
{
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnIntoDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileDataList) */
|
||
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnOutOfDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileDataList)
|
||
{
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnOutOfDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileDataList) */
|
||
|
||
public:
|
||
};/*
|
||
class ZCViewDirOfFileList*/
|
||
|
||
|
||
/*/////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ class ZCViewFileOfDir 는 특정 디렉토리에서 첫번째 깊이의 디렉토리만 저장한다.
|
||
|
||
-- 2012-10-21 16:53:00
|
||
|
||
/////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
class ZCViewFileOfDir
|
||
{
|
||
public:
|
||
|
||
template<typename TDirNameListRef> ZNsMain::ZNsEnum::ZERun
|
||
OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TDirNameListRef ARR_CDirNameList)
|
||
{
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TDirNameListRef> ZNsMain::ZNsEnum::ZERun
|
||
OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TDirNameListRef ARR_CDirNameList) */
|
||
|
||
template<typename TDirNameListRef> ZNsMain::ZNsEnum::ZERun OnDir(
|
||
ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TDirNameListRef ARR_CDirNameList)
|
||
{
|
||
typedef typename ZNsMain::ZtCTypeData
|
||
<TDirNameListRef>::TypeData::TypeData CStringData;
|
||
|
||
CStringData VO_CStringPath; VO_CStringPath(APC_NowPath)
|
||
(ZNsMain::ZNsConst::CPC_DirDelimiter)(AR_CFileData.GetFileName()); ///////
|
||
|
||
ARR_CDirNameList.push_back(VO_CStringPath); return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TDirNameListRef> ZNsMain::ZNsEnum::ZERun OnDir(
|
||
ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TDirNameListRef ARR_CDirNameList) */
|
||
|
||
public:
|
||
};/*
|
||
class ZCViewFileOfDir*/
|
||
|
||
|
||
class ZCViewFileDataList
|
||
{
|
||
public:
|
||
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileList)
|
||
{
|
||
ARR_CFileList.push_back(AR_CFileData); return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileList) */
|
||
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileList)
|
||
{
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
}/*
|
||
template<typename TFileDataListRef> _NP_ ZNsMain::ZNsEnum::ZERun
|
||
OnDir(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TFileDataListRef ARR_CFileList) */
|
||
|
||
public:
|
||
};/*
|
||
class ZCViewFileDataList*/
|
||
|
||
}/*
|
||
namespace ZNsIFace*/
|
||
|
||
|
||
class ZCDir
|
||
{
|
||
public:
|
||
|
||
|
||
class ZCExceptDir : public ZCExceptBase
|
||
{
|
||
protected:
|
||
std::string mo_CStrFileName;
|
||
std::string mo_CStrMessage ;
|
||
public :
|
||
|
||
ZCExceptDir(const char* AP_FileName, const char* AP_Message=0)
|
||
{
|
||
if(AP_FileName!=0) mo_CStrFileName=AP_FileName;
|
||
if(AP_Message !=0) mo_CStrMessage =AP_Message ;
|
||
}/*
|
||
ZCExceptDir(const char* AP_FileName, const char* AP_Message=0)*/
|
||
|
||
std::string& GetFileName(){return mo_CStrFileName;}
|
||
std::string& GetMessage (){return mo_CStrMessage ;}
|
||
|
||
public:
|
||
};/*
|
||
class ZCExceptDir
|
||
|
||
|
||
public:*/
|
||
public:
|
||
|
||
|
||
inline static bool DoExist(const char* AP_FileName, int AI_Mode=0)
|
||
{
|
||
/* AI_Mode 가 0 이면 파일의 존재를 조사하며,
|
||
2 이면 읽기, 4면 쓰기, 6 이면 읽기 쓰기 모두 가능한지 조사한다.
|
||
요청한 액세스 타입이 맞으면 0, 그렇지 않으면 -1 을 리턴. */
|
||
|
||
return ::access(AP_FileName, AI_Mode)==0 ;
|
||
}/*
|
||
inline static bool DoExist(const char* AP_FileName, int AI_Mode=0)*/
|
||
|
||
inline static bool DoExist(const wchar_t* AP_FileName, int AI_Mode=0)
|
||
{
|
||
/* AI_Mode 가 0 이면 파일의 존재를 조사하며,
|
||
2 이면 읽기, 4면 쓰기, 6 이면 읽기 쓰기 모두 가능한지 조사한다.
|
||
요청한 액세스 타입이 맞으면 0, 그렇지 않으면 -1 을 리턴. */
|
||
|
||
char VCA_TempBuf[_MAX_PATH2];
|
||
|
||
::wcstombs(
|
||
VCA_TempBuf, AP_FileName, ZNsMain::ZftLength(AP_FileName));
|
||
|
||
return ::access(VCA_TempBuf,AI_Mode)==0 ;
|
||
}/*
|
||
inline static bool DoExist(const wchar_t* AP_FileName, int AI_Mode=0)*/
|
||
|
||
|
||
template<typename TTypChar> static const TTypChar*
|
||
GetExtName(const TTypChar* APC_FileName, ZTypLength AI_Length)
|
||
{
|
||
// 파일의 확장자를 가져온다.
|
||
|
||
if(AI_Length<1) return 0;
|
||
|
||
for(int VI_Index=AI_Length-1; VI_Index>=0; --VI_Index)
|
||
{
|
||
if(APC_FileName[VI_Index]=='.') return APC_FileName+VI_Index+1 ;
|
||
}/*
|
||
for(int VI_Index=AI_Length-1; VI_Index>=0; --VI_Index)*/
|
||
|
||
return 0;
|
||
}/*
|
||
template<typename TTypChar> static const TTypChar*
|
||
GetExtName(const TTypChar* APC_FileName, ZTypLength AI_Length)*/
|
||
|
||
template<typename TTypChar> static const TTypChar* GetExtName
|
||
(
|
||
const TTypChar* APC_FileName,
|
||
ZTypLength AI_Length ,
|
||
ZTypLength& ARRI_LenExt
|
||
)
|
||
/////////////////////////////////////////////////////////////
|
||
{
|
||
if(AI_Length<1) return 0;
|
||
|
||
for(int VI_Index=AI_Length-1; VI_Index>=0; --VI_Index)
|
||
{
|
||
if(APC_FileName[VI_Index]=='.')
|
||
{
|
||
ARRI_LenExt=AI_Length-(VI_Index+1); return APC_FileName+VI_Index+1 ;
|
||
}/*
|
||
if(APC_FileName[VI_Index]=='.')*/
|
||
}/*
|
||
for(int VI_Index=AI_Length-1; VI_Index>=0; --VI_Index)*/
|
||
|
||
ARRI_LenExt=0; return 0;
|
||
}/*
|
||
template<typename TTypChar> static const TTypChar* GetExtName
|
||
(
|
||
const TTypChar* APC_FileName,
|
||
ZTypLength AI_Length ,
|
||
ZTypLength& ARRI_LenExt
|
||
)
|
||
///////////////////////////////////////////////////////////*/
|
||
|
||
template<typename TString, typename TTypChar> ///////////////
|
||
static TString& GetExtName
|
||
(
|
||
const TTypChar* APC_FileName ,
|
||
ZTypLength AI_Length ,
|
||
TString& ARR_CStringExt
|
||
)
|
||
/////////////////////////////////////////////////////////////
|
||
{
|
||
if(AI_Length<1) return ARR_CStringExt;
|
||
|
||
|
||
int VI_Index=AI_Length-1;
|
||
|
||
for(; VI_Index>=0; --VI_Index)
|
||
{
|
||
if(APC_FileName[VI_Index]=='.') break;
|
||
}/*
|
||
for(; VI_Index>=0; --VI_Index)*/
|
||
|
||
if(VI_Index<0) return ARR_CStringExt;
|
||
|
||
return ARR_CStringExt
|
||
( APC_FileName+VI_Index+1, AI_Length-(VI_Index+1) );
|
||
}/*
|
||
template<typename TString, typename TTypChar> ///////////////
|
||
static TString& GetExtName
|
||
(
|
||
const TTypChar* APC_FileName ,
|
||
ZTypLength AI_Length ,
|
||
TString& ARR_CStringExt
|
||
)
|
||
///////////////////////////////////////////////////////////*/
|
||
|
||
|
||
template<typename TString, typename TTypChar> static bool SetExtName
|
||
(
|
||
const TTypChar* APC_FileName, ZTypLength AI_FileLen ,
|
||
const TTypChar* APC_FileExt , ZTypLength AI_ExtLength,
|
||
TString& ARR_CStringFileNew
|
||
)
|
||
/*################################################################*/
|
||
{
|
||
// APC_FileName 의 확장자를 APC_FileExt 으로 바꾼
|
||
// 새로운 파일명을 ARR_CStringFileNew 에 전달한다.
|
||
|
||
ZTypLength VL_ExtPos=ZCMainChars::FindPosFromEnd
|
||
(
|
||
APC_FileName, TTypChar(".") ,
|
||
AI_FileLen , (ZTypLength)1
|
||
);
|
||
/**********************************************/
|
||
|
||
if(VL_ExtPos<0 || VL_ExtPos==AI_FileLen-1)
|
||
{
|
||
ARR_CStringFileNew.append(APC_FileName, AI_FileLen); return false;
|
||
}
|
||
else if(VL_ExtPos==0)
|
||
{
|
||
ARR_CStringFileNew+=".";
|
||
ARR_CStringFileNew.append(APC_FileExt, AI_ExtLength);
|
||
|
||
return true;
|
||
}/*
|
||
else if(VL_ExtPos==0)*/
|
||
|
||
ARR_CStringFileNew.append(APC_FileName , VL_ExtPos );
|
||
ARR_CStringFileNew.append(TTypChar('.') );
|
||
ARR_CStringFileNew.append(APC_FileExt , AI_ExtLength );
|
||
|
||
return true;
|
||
}/*
|
||
template<typename TString, typename TTypChar> static bool SetExtName
|
||
(
|
||
const TTypChar* APC_FileName, ZTypLength AI_FileLen ,
|
||
const TTypChar* APC_FileExt , ZTypLength AI_ExtLength,
|
||
TString& ARR_CStringFileNew
|
||
)
|
||
##################################################################*/
|
||
|
||
|
||
template<typename TString> static bool SetExtName(
|
||
const TString& AR_CStringFileNow, const TString& AR_CStringNewExt, TString& ARR_CStringFileNew)
|
||
{
|
||
return SetExtName /**************/
|
||
(
|
||
AR_CStringFileNow.data() ,
|
||
AR_CStringFileNow.size() ,
|
||
AR_CStringNewExt .data() ,
|
||
AR_CStringNewExt .size() ,
|
||
RR(ARR_CStringFileNew)
|
||
);
|
||
/********************************/
|
||
}/*
|
||
template<typename TString> static bool SetExtName(
|
||
const TString& AR_CStringFileNow, const TString& AR_CStringNewExt, TString& ARR_CStringFileNew) */
|
||
|
||
|
||
template<typename TString, typename TCharView> static bool SetExtName
|
||
(
|
||
const TCharView& AR_FileName, const TCharView& AR_FileExt, TString& ARR_CStringFileNew
|
||
)
|
||
/*#################################################################*/
|
||
{
|
||
return SetExtName /***************************/
|
||
(
|
||
AR_FileName.data(), AR_FileName.size(),
|
||
AR_FileExt .data(), AR_FileExt .size()
|
||
);
|
||
/*********************************************/
|
||
}
|
||
/*#################################################################*/
|
||
|
||
|
||
template<typename TString, typename TTypChar> static bool SetFileName
|
||
(
|
||
const TTypChar* APC_FileNow, ZTypLength AI_FileNowLen,
|
||
const TTypChar* APC_FileNew, ZTypLength AI_FileNewLen,
|
||
TString& ARR_CStringFileNew
|
||
)
|
||
/////////////////////////////////////////////////////////////////////
|
||
{
|
||
/* 파일 APC_FileNow 의 확장자를 뺀 부분을 APC_FileNew 으로 바꾼,
|
||
새로운 파일명을 ARR_CStringFileNew 에 전달한다. */
|
||
|
||
ZTypLength VL_ExtPos=ZCMainChars::FindPos
|
||
(
|
||
APC_FileNow , ".", AI_FileNowLen, 1
|
||
);
|
||
/***************************************/
|
||
|
||
if(VL_ExtPos<0)
|
||
{ ARR_CStringFileNew.append(APC_FileNew, AI_FileNewLen); return false; }
|
||
else if(VL_ExtPos==0)
|
||
{ ARR_CStringFileNew.append(APC_FileNow, AI_FileNowLen); return true ; }
|
||
/*else if(VL_ExtPos==0)*/
|
||
|
||
ARR_CStringFileNew.append(APC_FileNew, AI_FileNewLen);
|
||
ARR_CStringFileNew.append('.');
|
||
|
||
if(VL_ExtPos<AI_FileNowLen-1)
|
||
{
|
||
ARR_CStringFileNew.append
|
||
(
|
||
APC_FileNow+VL_ExtPos+1, AI_FileNowLen-VL_ExtPos-1
|
||
);
|
||
}
|
||
return true; /**************/
|
||
}/*
|
||
template<typename TString, typename TTypChar> static bool SetFileName
|
||
(
|
||
const TTypChar* APC_FileNow, ZTypLength AI_FileNowLen,
|
||
const TTypChar* APC_FileNew, ZTypLength AI_FileNewLen,
|
||
TString& ARR_CStringFileNew
|
||
)
|
||
///////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
template<typename TString> static bool SetFileName(
|
||
const TString& AR_CStringFileNow, const TString& AR_CStringNewExt, TString& ARR_CStringFileNew)
|
||
{
|
||
return SetFileName /**************************************/
|
||
(
|
||
AR_CStringFileNow.data(), AR_CStringFileNow.size(),
|
||
AR_CStringNewExt .data(), AR_CStringNewExt .size(),
|
||
RR(ARR_CStringFileNew)
|
||
);
|
||
/*********************************************************/
|
||
}/*
|
||
template<typename TString> static bool SetFileName(
|
||
const TString& AR_CStringFileNow, const TString& AR_CStringNewExt, TString& ARR_CStringFileNew) */
|
||
|
||
|
||
template<typename TTypChar> static const TTypChar* GetFileNameInPath
|
||
(
|
||
const TTypChar* APC_PathName,
|
||
ZTypLength AI_Length ,
|
||
ZTypLength& ARRI_FileName
|
||
)
|
||
////////////////////////////////////////////////////////////////////
|
||
{
|
||
// 디렉토리명을 포함한 파일명 APC_PathName 에서 파일명 부분만 추출한다.
|
||
|
||
if(AI_Length<1) return 0;
|
||
|
||
using namespace ZNsMain::ZNsChars ;
|
||
using ZNsMain::ZNsConst::CPC_DirDelimiter ;
|
||
|
||
typedef ZNsChars::ZNsType::
|
||
ZtCTypeChars<TTypChar> ZCTypeChars ;
|
||
|
||
ZTypLength VL_FindPos = ZCTypeChars::FindPosFromEnd
|
||
( APC_PathName, CPC_DirDelimiter, AI_Length, 1 ) ;
|
||
|
||
if(VL_FindPos<0)
|
||
{
|
||
ARRI_FileName=AI_Length; return APC_PathName;
|
||
}
|
||
ARRI_FileName=AI_Length-(VL_FindPos+1);
|
||
|
||
return APC_PathName+VL_FindPos+1;
|
||
}/*
|
||
template<typename TTypChar> static const TTypChar* GetFileNameInPath
|
||
(
|
||
const TTypChar* APC_PathName,
|
||
ZTypLength AI_Length ,
|
||
ZTypLength& ARRI_FileName
|
||
)
|
||
//////////////////////////////////////////////////////////////////*/
|
||
|
||
template<typename TString, typename TTypChar>
|
||
static TString& GetFileNameInPath
|
||
(const TTypChar* APC_PathName, ZTypLength AI_Length, TString& ARR_FileNameCStr)
|
||
{
|
||
ZTypLength VL_Length= 0 ;
|
||
const char* VPC_File = GetFileNameInPath
|
||
( APC_PathName, AI_Length, RR(VL_Length) );
|
||
|
||
if(VL_Length>0)
|
||
ARR_FileNameCStr(VPC_File, VL_Length);
|
||
|
||
return ARR_FileNameCStr;
|
||
}/*
|
||
template<typename TString, typename TTypChar>
|
||
static TString& GetFileNameInPath
|
||
(const TTypChar* APC_PathName, ZTypLength AI_Length, TString& ARR_FileNameCStr)*/
|
||
|
||
template<typename TChars,typename TString>
|
||
static TString& GetFileNameInPath(const TChars& AR_PathName, TString& ARR_FileNameCStr)
|
||
{
|
||
return GetFileNameInPath(AR_PathName.data(), AR_PathName.size(), RR(ARR_FileNameCStr));
|
||
}/*
|
||
template<typename TChars,typename TString>
|
||
static TString& GetFileNameInPath(const TChars& AR_PathName, TString& ARR_FileNameCStr) */
|
||
|
||
|
||
static bool RmAnyDir ///////////////////////////////////////////////////////////////////
|
||
( ZTypCPCh AP_DirName, void (*APF_ExceptHandle)
|
||
(
|
||
ZTypCPCh AP_FileName, ZCFileData& AR_CFileData, ZTypCPCCh AP_Message
|
||
)
|
||
)
|
||
/*####################################################################################*/
|
||
{
|
||
#if defined(_WIN)
|
||
|
||
ZTypChar VCA_Search[_MAX_PATH2+1]={_T('0')};
|
||
|
||
::strcpy(VCA_Search, AP_DirName );
|
||
::strcat(VCA_Search, "\\*.*" );
|
||
|
||
BOOL VB_IsSearched=TRUE ;
|
||
bool VB_RemoveFail=false;
|
||
|
||
ZCFileData VO_CFileData ; HANDLE VH_File =
|
||
::FindFirstFileA( VCA_Search, &VO_CFileData ) ;
|
||
|
||
if(VH_File==INVALID_HANDLE_VALUE){ return false; }
|
||
|
||
do //////
|
||
{
|
||
// If the attribute of the file is FILE_ATTRIBUTE_READONLY,
|
||
// change the file attribute to FILE_ATTRIBUTE_NORNAL
|
||
|
||
if( ::strcmp("." , VO_CFileData.cFileName)==0 ||
|
||
::strcmp("..", VO_CFileData.cFileName)==0 )
|
||
{
|
||
continue;
|
||
}
|
||
/*
|
||
if( ::strcmp("." , VO_CFileData.cFileName)==0 ||
|
||
::strcmp("..", VO_CFileData.cFileName)==0 )
|
||
*/
|
||
|
||
strcpy(VCA_Search, AP_DirName);
|
||
strcat(VCA_Search, "\\" );
|
||
strcat(VCA_Search, VO_CFileData.cFileName);
|
||
|
||
if(VO_CFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
||
{ ::SetFileAttributesA(VCA_Search, FILE_ATTRIBUTE_NORMAL); }
|
||
|
||
if(VO_CFileData.IsDir()) // VO_CFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||
{
|
||
if(RmAnyDir(VCA_Search, APF_ExceptHandle)==false)
|
||
{
|
||
APF_ExceptHandle(
|
||
VCA_Search, VO_CFileData, "RmAnyDir() return false");
|
||
|
||
VB_RemoveFail=true; break;
|
||
}/*
|
||
if(RmAnyDir(VCA_Search,APF_ExceptHandle)==false)*/
|
||
}
|
||
else if(::DeleteFileA(VCA_Search)==FALSE)
|
||
{
|
||
APF_ExceptHandle(
|
||
VCA_Search, VO_CFileData, "DeleteFile() return false");
|
||
|
||
VB_RemoveFail=true; break;
|
||
}/*
|
||
else if(::DeleteFileA(VCA_Search)==FALSE)*/
|
||
|
||
VB_RemoveFail=false;
|
||
}
|
||
while((VB_IsSearched = ::FindNextFileA(VH_File, &VO_CFileData))==TRUE);
|
||
|
||
::FindClose(VH_File);
|
||
|
||
if(VB_RemoveFail==true)
|
||
{
|
||
return false;
|
||
}
|
||
if(::RemoveDirectoryA(AP_DirName)==FALSE)
|
||
{
|
||
if(APF_ExceptHandle!=0)
|
||
APF_ExceptHandle(AP_DirName, VO_CFileData, "Fail to RemoveDirectory");
|
||
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
return true;
|
||
}/*
|
||
else*/
|
||
|
||
#elif defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_) // && !defined(_WIN)
|
||
|
||
ZCFileData VO_CFileData;
|
||
dirent VO_DirEnt ;
|
||
dirent* VP_DirEnt=0 ;
|
||
TypeDirID VH_File = ::opendir(AP_DirName);
|
||
bool VB_RemoveFail= false ;
|
||
|
||
if(VH_File==NULL)
|
||
{ return false; }
|
||
|
||
::chdir(AP_DirName);
|
||
|
||
/*//////////////////////////////////////////////////////////////////
|
||
|
||
■ In dirent.h
|
||
|
||
#ifndef __USE_FILE_OFFSET64
|
||
extern struct dirent *readdir (DIR *__dirp) __nonnull ((1));
|
||
#else
|
||
# ifdef __REDIRECT
|
||
extern struct dirent *__REDIRECT (readdir, (DIR *__dirp), readdir64)
|
||
__nonnull ((1));
|
||
# else
|
||
# define readdir readdir64
|
||
# endif
|
||
#endif
|
||
|
||
-- 2009-12-21 23:41:00
|
||
|
||
■ 아래는 naver 에서 Visual C++ __REDIRECT 로 검색한 것.
|
||
|
||
Visual C++의 __REDIRECT 매크로는 특정 함수 호출을 다른 함수로 리디렉션
|
||
(재지정)하는 역할을 하며, 주로 Windows API에서 사용됩니다. 이 매크로는
|
||
함수 포인터를 통해 원래 함수의 동작을 다른 함수로 대체할 수 있도록 해
|
||
줍니다.
|
||
|
||
__REDIRECT의 주요 특징
|
||
|
||
함수 리디렉션: __REDIRECT는 호출되는 함수를 다른 함수로 변경할 수 있도
|
||
록 하여, 디버그/릴리즈 모드나 특정 플랫폼에서의 동작을 제어할 수 있습니
|
||
다.
|
||
|
||
Windows API 호환성: 주로 Windows API에서 사용되며, 함수 포인터를 통해
|
||
원본 함수의 인자 변환 규칙을 유지하면서 다른 함수로 연결할 수 있습니다.
|
||
|
||
컴파일러 옵션: Visual C++ 컴파일러의 특정 옵션을 통해 정의되며, 함수의
|
||
반환 타입과 인자 변환 규칙을 지정할 수 있습니다.
|
||
|
||
사용 예시 및 유의점
|
||
디버그/릴리즈 모드 차이: __REDIRECT는 컴파일러 옵션에 따라 동작 방식이
|
||
달라질 수 있으므로, 개발 환경에 맞는 설정이 필요합니다.
|
||
|
||
호환성: 오래된 Windows 버전이나 타겟 플랫폼에서는 지원되지 않을 수 있
|
||
으니, 사용 전 호환성을 반드시 확인해야 합니다.
|
||
|
||
__REDIRECT는 Windows API 개발에서 함수 우회, 디버그/릴리즈 모드 최적화
|
||
등에 널리 활용되는 매크로입니다
|
||
|
||
-- 2025-08-15 14:27
|
||
|
||
//////////////////////////////////////////////////////////////////*/
|
||
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
{
|
||
const bool CB_IsNotValid = ////////////////////
|
||
(
|
||
::strcmp(".", VP_DirEnt->d_name)==0 ||
|
||
::strcmp("..", VP_DirEnt->d_name)==0 ||
|
||
VO_DirEnt.d_ino==0
|
||
);
|
||
///////////////////////////////////////////////
|
||
|
||
if(CB_IsNotValid) continue;
|
||
|
||
if(::lstat(VP_DirEnt->d_name, &VO_CFileData)<0)
|
||
{
|
||
APF_ExceptHandle(
|
||
VP_DirEnt->d_name, VO_CFileData, "lstat Error");
|
||
|
||
VB_RemoveFail=true; break;
|
||
}/*
|
||
if(::lstat(VP_DirEnt->d_name, &VO_CFileData)<0)*/
|
||
|
||
if(VO_CFileData.IsDir()) // S_ISDIR(VO_CFileData.st_mode))
|
||
{
|
||
if(RmAnyDir(VP_DirEnt->d_name, APF_ExceptHandle)==false)
|
||
{
|
||
APF_ExceptHandle(
|
||
VP_DirEnt->d_name, VO_CFileData, "RmAnyDir() return false");
|
||
|
||
VB_RemoveFail=true; break;
|
||
}/*
|
||
if(RmAnyDir(VP_DirEnt->d_name, APF_ExceptHandle)==false)*/
|
||
}
|
||
else
|
||
{
|
||
if(::unlink(VP_DirEnt->d_name)!=0)
|
||
{
|
||
APF_ExceptHandle(
|
||
VP_DirEnt->d_name, VO_CFileData, "DeleteFile() return false");
|
||
|
||
VB_RemoveFail=true; break;
|
||
}/*
|
||
if(::unlink(VP_DirEnt->d_name)!=0)*/
|
||
}/*
|
||
else*/
|
||
|
||
VB_RemoveFail=false;
|
||
}/*
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)*/
|
||
|
||
::chdir(".."); ::closedir(VH_File);
|
||
|
||
if(VP_DirEnt ==0 ) {return false;}
|
||
if(VB_RemoveFail==true) {return false;}
|
||
|
||
::rmdir(AP_DirName); return true ;
|
||
|
||
//#elif defined(_REENTRANT) // && !defined(_WIN)
|
||
#else // !defined(_WIN) && !defined(_REENTRANT) || defined(_NO_USE_REEDDIR_R_)
|
||
|
||
ZCFileData VO_CFileData;
|
||
dirent* VP_DirEnt ;
|
||
TypeDirID VH_File = ::opendir(AP_DirName) ;
|
||
bool VB_RemoveFail= false ;
|
||
|
||
if(VH_File==NULL) return false;
|
||
|
||
::chdir(AP_DirName);
|
||
|
||
/*//////////////////////////////////////////////////////////////////
|
||
|
||
■ In dirent.h
|
||
|
||
#ifndef __USE_FILE_OFFSET64
|
||
extern struct dirent *readdir (DIR *__dirp) __nonnull ((1));
|
||
#else
|
||
# ifdef __REDIRECT
|
||
extern struct dirent *__REDIRECT (readdir, (DIR *__dirp), readdir64)
|
||
__nonnull ((1));
|
||
# else
|
||
# define readdir readdir64
|
||
# endif
|
||
#endif
|
||
|
||
-- 2009-12-21 23:41:00
|
||
|
||
//////////////////////////////////////////////////////////////////*/
|
||
|
||
while((VP_DirEnt = ::readdir(VH_File))!=0)
|
||
{
|
||
const bool CB_IsNotValid = ////////////////////
|
||
(
|
||
::strcmp(".", VP_DirEnt->d_name)==0 ||
|
||
::strcmp("..", VP_DirEnt->d_name)==0 ||
|
||
VP_DirEnt->d_ino==0
|
||
);
|
||
///////////////////////////////////////////////
|
||
|
||
if(CB_IsNotValid) continue;
|
||
|
||
if(lstat(VP_DirEnt->d_name, &VO_CFileData)<0)
|
||
{
|
||
APF_ExceptHandle(VP_DirEnt->d_name, VO_CFileData, "lstat Error");
|
||
|
||
VB_RemoveFail=true; break; /*##################################*/
|
||
}/*
|
||
if(lstat(VP_DirEnt->d_name, &VO_CFileData)<0)*/
|
||
|
||
if(VO_CFileData.IsDir()) // S_ISDIR(VO_CFileData.st_mode))
|
||
{
|
||
if(RmAnyDir(VP_DirEnt->d_name, APF_ExceptHandle)==false)
|
||
{
|
||
APF_ExceptHandle(VP_DirEnt->d_name, VO_CFileData, "RmAnyDir return false");
|
||
|
||
VB_RemoveFail=true; break; /*############################################*/
|
||
}/*
|
||
if(RmAnyDir(VP_DirEnt->d_name, APF_ExceptHandle)==false)*/
|
||
}
|
||
else
|
||
{
|
||
::unlink(VP_DirEnt->d_name);
|
||
}/*
|
||
else*/
|
||
|
||
VB_RemoveFail=false;
|
||
}/*
|
||
while((VP_DirEnt = ::readdir(VH_File))!=0)*/
|
||
|
||
::chdir(".."); ::closedir(VH_File);
|
||
|
||
if(VP_DirEnt ==0 ) return false;
|
||
if(VB_RemoveFail==true) return false;
|
||
|
||
::rmdir(AP_DirName); return true ;
|
||
|
||
#endif //!defined(_WIN) && !defined(_REENTRANT)
|
||
}/*
|
||
static bool RmAnyDir //////////////////////////////////////////////////////////////////
|
||
(
|
||
ZTypCPCh AP_DirName ,
|
||
void (*APF_ExceptHandle)
|
||
(ZTypCPCh AP_FileName, ZCFileData& AR_CFileData, ZTypCPCCh AP_Message)
|
||
)
|
||
######################################################################################*/
|
||
|
||
/*//////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ int _mkdir (const char *dirname);
|
||
int _wmkdir (const wchar_t *dirname);
|
||
|
||
Parameter
|
||
dirname
|
||
Path for new directory.
|
||
Return Value
|
||
Each of these functions returns the value 0 if the new directory was created. On an error the function returns ?1 and sets errno as follows:
|
||
|
||
EEXIST
|
||
Directory was not created because dirname is the name of an existing file, directory, or device.
|
||
ENOENT
|
||
Path was not found.
|
||
|
||
int _rmdir (const char *dirname );
|
||
int _wrmdir (const wchar_t *dirname );
|
||
Parameters
|
||
dirname
|
||
Path of directory to be removed.
|
||
Return Value
|
||
Each of these functions returns 0 if the directory is successfully deleted. A return value of ?1 indicates an error, and errno is set to one of the following values:
|
||
|
||
ENOTEMPTY
|
||
Given path is not a directory; directory is not empty; or directory is either current working directory or root directory.
|
||
ENOENT
|
||
Path is invalid.
|
||
EACCESS
|
||
A program has an open handle to the directory.
|
||
See _doserrno, errno, _sys_errlist, and _sys_nerr for more information on these and other return codes.
|
||
|
||
int _unlink( const char *filename );
|
||
int _wunlink( const wchar_t *filename );
|
||
|
||
Routine Required Header Compatibility
|
||
_unlink <io.h> and <stdio.h> Win 95, Win NT
|
||
_wunlink <io.h> or <wchar.h> Win NT
|
||
|
||
For additional compatibility information,
|
||
see Compatibility in the Introduction.
|
||
|
||
Libraries
|
||
|
||
LIBC.LIB Single thread static library, retail version
|
||
LIBCMT.LIB Multithread static library, retail version
|
||
MSVCRT.LIB Import library for MSVCRT.DLL, retail version
|
||
|
||
Return Value
|
||
|
||
Each of these functions returns 0 if successful.
|
||
Otherwise, the function returns ?1 and sets errno to EACCES,
|
||
which means the path specifies a read-only file, or to ENOENT,
|
||
which means the file or path is not found or the path specified a directory.
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
// APC_DirPath 는 디렉토리 구분자로 끝나지 않게 하자.
|
||
|
||
static ZNsMain::ZNsEnum::ZERun IterDirectory
|
||
(
|
||
ZTypCPCh APC_DirPath, void* APC_VoidKey,
|
||
ZNsMain::ZNsEnum::ZERun (*APF_EachFile)(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey),
|
||
ZNsMain::ZNsEnum::ZERun (*APF_IntoDir )(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey)=0,
|
||
ZNsMain::ZNsEnum::ZERun (*APF_OutOfDir)(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey)=0
|
||
)
|
||
////////////////////////////////////////////
|
||
{
|
||
ZNsMain::ZNsEnum::ZERun VE_ERun = ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_WIN)
|
||
|
||
ZTypChar VCA_Search[_MAX_PATH2+1]={'0'};
|
||
::strcpy(VCA_Search, APC_DirPath);
|
||
::strcat(VCA_Search, "\\*.*" );
|
||
|
||
ZCFileData VO_CFileData ;
|
||
BOOL VB_IsSearched= TRUE ;
|
||
HANDLE VH_File =
|
||
::FindFirstFileA(VCA_Search, &VO_CFileData);
|
||
|
||
if(VH_File==INVALID_HANDLE_VALUE) return ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
|
||
while(VB_IsSearched)
|
||
{
|
||
if( VO_CFileData.IsDir() ) // VO_CFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||
{
|
||
const bool CB_IsTrue =
|
||
(
|
||
::strcmp("." , VO_CFileData.cFileName)!=0 &&
|
||
::strcmp("..", VO_CFileData.cFileName)!=0
|
||
) ;
|
||
//////////////////////
|
||
|
||
if(CB_IsTrue)
|
||
{
|
||
::strcpy(VCA_Search, APC_DirPath);
|
||
::strcat(VCA_Search, "\\" );
|
||
::strcat(VCA_Search, VO_CFileData.cFileName);
|
||
|
||
// VCA_Search is a directory name
|
||
|
||
if(APF_IntoDir!=0)
|
||
{
|
||
if(APF_IntoDir(VCA_Search, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_IntoDir(VCA_Search, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
if(APF_IntoDir!=0)*/
|
||
|
||
if(IterDirectory(VCA_Search, APC_VoidKey, APF_EachFile, APF_IntoDir, APF_OutOfDir)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(IterDirectory(VCA_Search, APC_VoidKey, APF_EachFile, APF_IntoDir, APF_OutOfDir)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
|
||
if(APF_OutOfDir!=0)
|
||
{
|
||
if(APF_OutOfDir(VCA_Search, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_OutOfDir(VCA_Search, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
if(APF_OutOfDir!=0)*/
|
||
}/*
|
||
if(CB_IsTrue)*/
|
||
}
|
||
else // !VO_CFileData.IsDir()
|
||
{
|
||
if(APF_EachFile(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_EachFile(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else // !VO_CFileData.IsDir()*/
|
||
|
||
VB_IsSearched = ::FindNextFileA(VH_File, &VO_CFileData);
|
||
}/*
|
||
while(VB_IsSearched)*/
|
||
|
||
::FindClose(VH_File);
|
||
|
||
#else //!defined(_WIN)
|
||
|
||
ZCFileData VO_CFileData;
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
dirent VO_DirEnt;
|
||
#endif
|
||
dirent* VP_DirEnt;
|
||
TypeDirID VH_File = ::opendir(APC_DirPath);
|
||
char VCA_Search[_MAX_PATH2+1]={'0'} ;
|
||
|
||
if(VH_File==NULL)
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt = ::readdir(VH_File))!=0)
|
||
#endif
|
||
{
|
||
const bool CB_IsNotValid =
|
||
(
|
||
::strcmp(".", VP_DirEnt->d_name)==0 ||
|
||
::strcmp("..", VP_DirEnt->d_name)==0
|
||
);
|
||
//////////////////////////
|
||
|
||
if(CB_IsNotValid) continue;
|
||
|
||
::strcpy(VCA_Search, APC_DirPath);
|
||
|
||
if(::strcmp(APC_DirPath, "/")!=0)
|
||
{ ::strcat(VCA_Search, "/"); } // Not to append "/" at the tail of root directory name
|
||
|
||
::strcat(VCA_Search , VP_DirEnt->d_name);
|
||
::strcpy(VO_CFileData.cFileName, VP_DirEnt->d_name);
|
||
|
||
if(::lstat(VCA_Search, &VO_CFileData)<0)
|
||
{
|
||
throw ZCExceptDir
|
||
(
|
||
VP_DirEnt->d_name, "Fatal Error In "
|
||
"ZCDir::IterDirectory() : Can't know the file info"
|
||
);
|
||
/////////////////
|
||
|
||
return ZNsMain::ZNsEnum::ZERun_NO;
|
||
}/*
|
||
if(::lstat(VCA_Search, &VO_CFileData)<0)*/
|
||
|
||
if(VO_CFileData.IsDir()) // S_ISDIR(VO_CFileData.st_mode))
|
||
{
|
||
if(APF_IntoDir!=0)
|
||
{
|
||
if(APF_IntoDir(VCA_Search, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_IntoDir(VCA_Search, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
if(APF_IntoDir!=0)*/
|
||
|
||
if(IterDirectory(VCA_Search, APC_VoidKey, APF_EachFile, APF_IntoDir, APF_OutOfDir)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(IterDirectory(VCA_Search, APC_VoidKey, APF_EachFile, APF_IntoDir, APF_OutOfDir)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
|
||
if(APF_OutOfDir!=0)
|
||
{
|
||
if(APF_OutOfDir(VCA_Search,VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_OutOfDir(VCA_Search,VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
if(APF_OutOfDir!=0)*/
|
||
}
|
||
else // !VO_CFileData.IsDir()
|
||
{
|
||
if(APF_EachFile(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_EachFile(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else // !VO_CFileData.IsDir()*/
|
||
}/*
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt = ::readdir(VH_File))!=0)
|
||
#endif
|
||
*/
|
||
|
||
::closedir(VH_File);
|
||
|
||
if(VP_DirEnt==0)
|
||
return ZNsMain::ZNsEnum::ZERun_NO;
|
||
|
||
#endif //!defined(_WIN)
|
||
|
||
return VE_ERun;
|
||
}/*
|
||
static ZNsMain::ZNsEnum::ZERun IterDirectory
|
||
(
|
||
ZTypCPCh APC_DirPath, void* APC_VoidKey,
|
||
ZNsMain::ZNsEnum::ZERun (*APF_EachFile)(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey),
|
||
ZNsMain::ZNsEnum::ZERun (*APF_IntoDir )(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey)=0,
|
||
ZNsMain::ZNsEnum::ZERun (*APF_OutOfDir)(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey)=0
|
||
)
|
||
//////////////////////////////////////////*/
|
||
|
||
|
||
/*/////////////////////////////////////////////////////////////////////
|
||
|
||
■ AR_CViewDir 는 ZNsMain::ZNsEnum::ZERun 을 리턴하는 아래 3 벰버를 가져야 한다.
|
||
AR_CViewDir.OnFile (ZTypCPCh APC_NowPath,ZCFileData& AR_CFileData)
|
||
AR_CViewDir.OnIntoDir (ZTypCPCh APC_NowPath,ZCFileData& AR_CFileData)
|
||
AR_CViewDir.OnOutOfDir(ZTypCPCh APC_NowPath,ZCFileData& AR_CFileData)
|
||
|
||
TViewDir 은 ZNsMain::ZNsIFace::ZCViewDir 형.
|
||
|
||
■ APC_DirPath 는 디렉토리 구분자로 끝나지 않게 하자.
|
||
|
||
■ IterDirEx(~) 함수가 디렉토리와 파일을 찾아내는 Logic 을 담당한다면
|
||
TViewDir 은 찾아낸 데이타에 대한 일종의 View 를 담당한다.
|
||
|
||
■ 예제 -- 2025-08-11 10:19
|
||
|
||
#include <iostream>
|
||
#include "ZCppMain/ZMainHeadEx.H"
|
||
|
||
int main()
|
||
{
|
||
ZNsMain::ZNsIFace::ZCViewDir VO_CViewDir;
|
||
ZNsMain::ZCDir::IterDirEx("..", VO_CViewDir);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////*/
|
||
|
||
template<typename TViewDir> static ZNsMain::ZNsEnum::ZERun
|
||
IterDirEx(ZTypCPCh APC_DirPath, TViewDir AR_CViewDir)
|
||
{
|
||
typedef typename ZNsMain::
|
||
ZtCTypeData<TViewDir>::TypeData TypeViewDir ;
|
||
|
||
TypeViewDir& VR_CViewDir = ZNsMain::
|
||
ZtCTypeData<TViewDir>::GetObjRef(AR_CViewDir);
|
||
|
||
|
||
ZNsMain::ZNsEnum::ZERun VE_ERun = ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_WIN)
|
||
|
||
ZTypChar VCA_Search[_MAX_PATH2+1]={'0'};
|
||
::strcpy(VCA_Search, APC_DirPath);
|
||
::strcat(VCA_Search, "\\*.*" );
|
||
|
||
ZCFileData VO_CFileData ;
|
||
BOOL VB_IsSearched= TRUE ;
|
||
HANDLE VH_File =
|
||
::FindFirstFileA(VCA_Search, &VO_CFileData);
|
||
|
||
if(VH_File==INVALID_HANDLE_VALUE)
|
||
{ return ZNsMain::ZNsEnum::ZERun_OK; }
|
||
|
||
while(VB_IsSearched)
|
||
{
|
||
if( VO_CFileData.IsDir() ) // VO_CFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||
{
|
||
const bool CB_IsTrue =
|
||
(
|
||
::strcmp("." , VO_CFileData.cFileName)!=0 &&
|
||
::strcmp("..", VO_CFileData.cFileName)!=0
|
||
);
|
||
//////////////////////
|
||
|
||
if(CB_IsTrue)
|
||
{
|
||
strcpy(VCA_Search, APC_DirPath);
|
||
strcat(VCA_Search, "\\" );
|
||
strcat(VCA_Search, VO_CFileData.cFileName);
|
||
|
||
// VCA_Search is a directory name
|
||
|
||
if(VR_CViewDir.OnIntoDir (VCA_Search, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}
|
||
if(IterDirEx<TViewDir> (VCA_Search, AR_CViewDir )==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}
|
||
if(VR_CViewDir.OnOutOfDir(VCA_Search, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewDir.OnOutOfDir(VCA_Search, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
if(CB_IsTrue)*/
|
||
}
|
||
else
|
||
{
|
||
if(VR_CViewDir.OnFile(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewDir.OnFile(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else*/
|
||
|
||
VB_IsSearched=::FindNextFile(VH_File, &VO_CFileData);
|
||
}/*
|
||
while(VB_IsSearched)*/
|
||
|
||
::FindClose(VH_File);
|
||
|
||
#else //!defined(_WIN)
|
||
|
||
ZCFileData VO_CFileData;
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
dirent VO_DirEnt;
|
||
#endif
|
||
dirent* VP_DirEnt;
|
||
TypeDirID VH_File = ::opendir(APC_DirPath);
|
||
char VCA_Search[_MAX_PATH2+1]={'0'} ;
|
||
|
||
if(VH_File==NULL)
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt = ::readdir(VH_File))!=0)
|
||
#endif
|
||
{
|
||
const bool CB_IsNotValid =
|
||
(
|
||
::strcmp(".", VP_DirEnt->d_name)==0 ||
|
||
::strcmp("..", VP_DirEnt->d_name)==0
|
||
);
|
||
//////////////////////////
|
||
|
||
if(CB_IsNotValid) continue;
|
||
|
||
::strcpy(VCA_Search, APC_DirPath);
|
||
|
||
if(::strcmp(APC_DirPath, "/")!=0)
|
||
{ ::strcat(VCA_Search, "/"); } // Not to append "/" at the tail of root directory name
|
||
|
||
::strcat(VCA_Search , VP_DirEnt->d_name);
|
||
::strcpy(VO_CFileData.cFileName, VP_DirEnt->d_name);
|
||
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)
|
||
{
|
||
throw ZCExceptDir
|
||
(
|
||
VP_DirEnt->d_name, "Fatal Error In "
|
||
"ZCDir::IterDirEx() : Can't know the file info"
|
||
);
|
||
/////////////////
|
||
|
||
return ZNsMain::ZNsEnum::ZERun_NO;
|
||
}/*
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)*/
|
||
|
||
if(VO_CFileData.IsDir()) // S_ISDIR(VO_CFileData.st_mode))
|
||
{
|
||
if(VR_CViewDir.OnIntoDir (VCA_Search, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}
|
||
if(IterDirEx<TViewDir> (VCA_Search, AR_CViewDir )==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}
|
||
if(VR_CViewDir.OnOutOfDir(VCA_Search, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewDir.OnOutOfDir(VCA_Search, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}
|
||
else
|
||
{
|
||
if(VR_CViewDir.OnFile(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewDir.OnFile(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else*/
|
||
}/*
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt = ::readdir(VH_File))!=0)
|
||
#endif
|
||
*/
|
||
|
||
::closedir(VH_File);
|
||
|
||
if(VP_DirEnt==0)
|
||
return ZNsMain::ZNsEnum::ZERun_NO ;
|
||
|
||
#endif //!defined(_WIN)
|
||
|
||
return VE_ERun;
|
||
}/*
|
||
template<typename TViewDir> static ZNsMain::ZNsEnum::ZERun
|
||
IterDirEx(ZTypCPCh APC_DirPath, TViewDir AR_CViewDir) */
|
||
|
||
/*//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ AR_CViewDir 는 ZNsMain::ZNsEnum::ZERun 을 리턴하는 아래 3 벰버를 가져야 한다.
|
||
|
||
AR_CViewDir.OnFile <TTypeHelp>(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp)
|
||
AR_CViewDir.OnIntoDir <TTypeHelp>(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp)
|
||
AR_CViewDir.OnOutOfDir<TTypeHelp>(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, TTypeHelp AR_CTypeHelp)
|
||
|
||
-- 2012-05-23 02:24:00
|
||
|
||
//////////////////////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
template
|
||
<typename TViewDir, typename TTypeHelp>
|
||
static ZNsMain::ZNsEnum::ZERun IterDirEx
|
||
( ZTypCPCh APC_DirPath, TViewDir AR_CViewDir, TTypeHelp AR_CTypeHelp )
|
||
{
|
||
using ZNsMain::ZNsEnum::ZERun ;
|
||
using ZNsMain::ZNsEnum::ZERun_OK;
|
||
using ZNsMain::ZNsEnum::ZERun_NO;
|
||
|
||
typedef typename ZNsMain::
|
||
ZtCTypeData<TViewDir>::TypeData TypeViewDir ;
|
||
|
||
TypeViewDir& VR_CViewDir = ZNsMain::
|
||
ZtCTypeData<TViewDir>::GetObjRef(AR_CViewDir);
|
||
ZERun VE_ERun = ZERun_OK;
|
||
|
||
#if defined(_WIN)
|
||
|
||
ZTypChar VCA_Search[_MAX_PATH2+1]={'0'};
|
||
::strcpy(VCA_Search, APC_DirPath);
|
||
::strcat(VCA_Search, "\\*.*" );
|
||
|
||
ZCFileData VO_CFileData ;
|
||
BOOL VB_IsSearched= TRUE ;
|
||
HANDLE VH_File =
|
||
::FindFirstFileA(VCA_Search, &VO_CFileData);
|
||
|
||
if(VH_File==INVALID_HANDLE_VALUE) return ZERun_OK;
|
||
|
||
while(VB_IsSearched)
|
||
{
|
||
if( VO_CFileData.IsDir() ) // VO_CFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||
{
|
||
const bool CB_IsTrue =
|
||
(
|
||
::strcmp("." , VO_CFileData.cFileName)!=0 &&
|
||
::strcmp("..", VO_CFileData.cFileName)!=0
|
||
) ;
|
||
//////////////////////
|
||
|
||
if(CB_IsTrue)
|
||
{
|
||
strcpy(VCA_Search, APC_DirPath);
|
||
strcat(VCA_Search, "\\" );
|
||
strcat(VCA_Search, VO_CFileData.cFileName);
|
||
|
||
// VCA_Search is a directory name
|
||
|
||
if(VR_CViewDir.template OnIntoDir <TTypeHelp>(VCA_Search, VO_CFileData, AR_CTypeHelp)==ZERun_NO)
|
||
{ VE_ERun=ZERun_NO; break; }
|
||
if(IterDirEx<TViewDir, TTypeHelp> (VCA_Search, AR_CViewDir , AR_CTypeHelp)==ZERun_NO)
|
||
{ VE_ERun=ZERun_NO; break; }
|
||
if(VR_CViewDir.template OnOutOfDir<TTypeHelp>(VCA_Search, VO_CFileData, AR_CTypeHelp)==ZERun_NO)
|
||
{ VE_ERun=ZERun_NO; break; }/*
|
||
if(VR_CViewDir.template OnOutOfDir<TTypeHelp>(VCA_Search, VO_CFileData, AR_CTypeHelp)==ZERun_NO)*/
|
||
}/*
|
||
if(CB_IsTrue)*/
|
||
}
|
||
else
|
||
{
|
||
if(AR_CViewDir.template OnFile<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZERun_NO)
|
||
{
|
||
VE_ERun=ZERun_NO; break;
|
||
}/*
|
||
if(AR_CViewDir.template OnFile<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZERun_NO)*/
|
||
}/*
|
||
else*/
|
||
|
||
VB_IsSearched = ::FindNextFile(VH_File, &VO_CFileData);
|
||
}/*
|
||
while(VB_IsSearched)*/
|
||
|
||
::FindClose(VH_File);
|
||
|
||
#else //!defined(_WIN)
|
||
|
||
ZCFileData VO_CFileData;
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
dirent VO_DirEnt ;
|
||
#endif
|
||
dirent* VP_DirEnt;
|
||
TypeDirID VH_File= ::opendir(APC_DirPath);
|
||
char VCA_Search[_MAX_PATH2+1]={'0'} ;
|
||
|
||
if(VH_File==NULL) return ZERun_OK;
|
||
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt= ::readdir(VH_File))!=0)
|
||
#endif
|
||
{
|
||
const bool CB_IsNotValid =
|
||
(
|
||
::strcmp(".", VP_DirEnt->d_name)==0 ||
|
||
::strcmp("..", VP_DirEnt->d_name)==0
|
||
);
|
||
//////////////////////////
|
||
|
||
if(CB_IsNotValid) continue;
|
||
|
||
::strcpy(VCA_Search, APC_DirPath);
|
||
|
||
if(::strcmp(APC_DirPath,"/")!=0)
|
||
{ ::strcat(VCA_Search, "/"); } // Not to append "/" at the tail of root directory name
|
||
|
||
::strcat(VCA_Search , VP_DirEnt->d_name);
|
||
::strcpy(VO_CFileData.cFileName, VP_DirEnt->d_name);
|
||
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)
|
||
{
|
||
throw ZCExceptDir
|
||
(
|
||
VP_DirEnt->d_name, "Fatal Error In "
|
||
"ZCDir::IterDirEx() : Can't know the file info"
|
||
);
|
||
/////////////////
|
||
|
||
return ZERun_NO ;
|
||
}/*
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)*/
|
||
|
||
if(VO_CFileData.IsDir()) // S_ISDIR(VO_CFileData.st_mode))
|
||
{
|
||
if(VR_CViewDir.template OnIntoDir <TTypeHelp>(VCA_Search, VO_CFileData, AR_CTypeHelp)==ZERun_NO)
|
||
{ VE_ERun=ZERun_NO; break; }
|
||
if(IterDirEx<TViewDir, TTypeHelp> (VCA_Search, AR_CViewDir , AR_CTypeHelp)==ZERun_NO)
|
||
{ VE_ERun=ZERun_NO; break; }
|
||
if(VR_CViewDir.template OnOutOfDir<TTypeHelp>(VCA_Search, VO_CFileData, AR_CTypeHelp)==ZERun_NO)
|
||
{ VE_ERun=ZERun_NO; break; }/*
|
||
if(VR_CViewDir.template OnOutOfDir<TTypeHelp>(VCA_Search, VO_CFileData, AR_CTypeHelp)==ZERun_NO)*/
|
||
}
|
||
else
|
||
{
|
||
if(VR_CViewDir.template OnFile<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZERun_NO)
|
||
{
|
||
VE_ERun=ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewDir.template OnFile<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZERun_NO)*/
|
||
}/*
|
||
else*/
|
||
}/*
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt= ::readdir(VH_File))!=0)
|
||
#endif
|
||
*/
|
||
|
||
::closedir(VH_File); if(VP_DirEnt==0) return ZERun_NO;
|
||
|
||
#endif //!defined(_WIN)
|
||
|
||
return VE_ERun;
|
||
}/*
|
||
template
|
||
<typename TViewDir, typename TTypeHelp>
|
||
static ZNsMain::ZNsEnum::ZERun IterDirEx
|
||
( ZTypCPCh APC_DirPath, TViewDir AR_CViewDir, TTypeHelp AR_CTypeHelp ) */
|
||
|
||
|
||
// APC_DirPath 는 디렉토리 구분자로 끝나지 않게 하자.
|
||
|
||
static ZNsMain::ZNsEnum::ZERun IterFile /*#################################*/
|
||
(
|
||
ZTypCPCh APC_DirPath, void* APC_VoidKey,
|
||
ZNsMain::ZNsEnum::ZERun (*APF_EachFile)(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey),
|
||
ZNsMain::ZNsEnum::ZERun (*APF_EachDir )(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey)=0
|
||
)
|
||
/*##########################################################################*/
|
||
{
|
||
ZNsMain::ZNsEnum::ZERun VE_ERun=ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_WIN)
|
||
|
||
ZTypChar VCA_Search[_MAX_PATH2+1]={'0'};
|
||
|
||
::strcpy(VCA_Search, APC_DirPath);
|
||
::strcat(VCA_Search, "\\*.*" );
|
||
|
||
ZCFileData VO_CFileData ;
|
||
BOOL VB_IsSearched = TRUE ;
|
||
HANDLE VH_File =
|
||
::FindFirstFileA(VCA_Search, &VO_CFileData);
|
||
|
||
if(VH_File==INVALID_HANDLE_VALUE)
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
while(VB_IsSearched)
|
||
{
|
||
if(VO_CFileData.IsDir()) // (VO_CFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||
{
|
||
const bool CB_Istrue =
|
||
(
|
||
::strcmp("." , VO_CFileData.cFileName)!=0 &&
|
||
::strcmp("..", VO_CFileData.cFileName)!=0
|
||
);
|
||
//////////////////////
|
||
|
||
if(CB_Istrue)
|
||
{
|
||
if(APF_EachDir!=0)
|
||
{
|
||
if(APF_EachDir(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_EachDir(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
if(APF_EachDir!=0)*/
|
||
}/*
|
||
if(CB_Istrue)*/
|
||
}
|
||
else // !VO_CFileData.IsDir()
|
||
{
|
||
if(APF_EachFile(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_EachFile(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else // !VO_CFileData.IsDir()*/
|
||
|
||
VB_IsSearched = ::FindNextFileA(VH_File, &VO_CFileData);
|
||
}/*
|
||
while(VB_IsSearched)*/
|
||
|
||
::FindClose(VH_File);
|
||
|
||
#else // !defined(_WIN)
|
||
|
||
ZCFileData VO_CFileData;
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
dirent VO_DirEnt;
|
||
#endif
|
||
dirent* VP_DirEnt;
|
||
TypeDirID VH_File = ::opendir(APC_DirPath) ;
|
||
char VCA_Search[_MAX_PATH2+1]={_T('0')};
|
||
|
||
if(VH_File==NULL)
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt= ::readdir(VH_File))!=0)
|
||
#endif
|
||
{
|
||
const bool CB_IsNotValid =
|
||
(
|
||
::strcmp(".", VP_DirEnt->d_name)==0 ||
|
||
::strcmp("..", VP_DirEnt->d_name)==0
|
||
);
|
||
//////////////////////////
|
||
|
||
if(CB_IsNotValid) continue;
|
||
|
||
::strcpy(VCA_Search,APC_DirPath);
|
||
|
||
if(::strcmp(APC_DirPath, "/")!=0)
|
||
{ ::strcat(VCA_Search, "/"); }
|
||
|
||
::strcat(VCA_Search , VP_DirEnt->d_name);
|
||
::strcpy(VO_CFileData.cFileName, VP_DirEnt->d_name);
|
||
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)
|
||
{
|
||
throw ZCExceptDir
|
||
(
|
||
VP_DirEnt->d_name, "Fatal Error "
|
||
"In ZCDir::IterFile() : Can't know the file info"
|
||
);
|
||
/////////////////
|
||
|
||
return ZNsMain::ZNsEnum::ZERun_NO;
|
||
}/*
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)*/
|
||
|
||
if( VO_CFileData.IsDir() )
|
||
{
|
||
if(APF_EachDir(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_EachDir(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}
|
||
else
|
||
{
|
||
if(APF_EachFile(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(APF_EachFile(APC_DirPath, VO_CFileData, APC_VoidKey)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else*/
|
||
}/*
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt= ::readdir(VH_File))!=0)
|
||
#endif*/
|
||
|
||
::closedir(VH_File);
|
||
|
||
if(VP_DirEnt==0)
|
||
return ZNsMain::ZNsEnum::ZERun_NO ;
|
||
|
||
#endif // !defined(_WIN)
|
||
|
||
return VE_ERun;
|
||
}/*
|
||
static ZNsMain::ZNsEnum::ZERun IterFile ####################################
|
||
(
|
||
ZTypCPCh APC_DirPath, void* APC_VoidKey,
|
||
ZNsMain::ZNsEnum::ZERun (*APF_EachFile)(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey),
|
||
ZNsMain::ZNsEnum::ZERun (*APF_EachDir )(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData, void* APC_VoidKey)=0
|
||
)
|
||
############################################################################*/
|
||
|
||
|
||
/*////////////////////////////////////////////////////
|
||
|
||
■ TViewFile 은 ZNsMain::ZNsEnum::ZERun 을 리턴하는 아래 멤버를 갖는다.
|
||
|
||
OnDir (ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)
|
||
OnFile(ZTypCPCh APC_NowPath, ZCFileData& AR_CFileData)
|
||
|
||
■ APC_DirPath 는 디렉토리 구분자로 끝나지 않게 하자.
|
||
|
||
////////////////////////////////////////////////////*/
|
||
|
||
template<typename TViewFile> static ZNsMain::ZNsEnum::
|
||
ZERun IterFileEx(ZTypCPCh APC_DirPath, TViewFile AR_CViewFile)
|
||
{
|
||
typedef typename ZNsMain::
|
||
ZtCTypeData<TViewFile>::TypeData TypeViewFile ;
|
||
|
||
TypeViewFile& VR_CViewFile = ZNsMain::
|
||
ZtCTypeData<TViewFile>::GetObjRef(AR_CViewFile);
|
||
|
||
|
||
ZNsMain::ZNsEnum::ZERun VE_ERun=ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_WIN)
|
||
|
||
ZTypChar VCA_Search[_MAX_PATH2+1]={'0'};
|
||
|
||
::strcpy(VCA_Search, APC_DirPath) ;
|
||
::strcat(VCA_Search, "\\*.*" ) ;
|
||
|
||
ZCFileData VO_CFileData ;
|
||
BOOL VB_IsSearched = TRUE ;
|
||
HANDLE VH_File =
|
||
::FindFirstFileA(VCA_Search, &VO_CFileData);
|
||
|
||
if(VH_File==INVALID_HANDLE_VALUE) return ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
while(VB_IsSearched)
|
||
{
|
||
if(VO_CFileData.IsDir()) // (VO_CFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||
{
|
||
const bool CB_IsTrue =
|
||
(
|
||
::strcmp("." , VO_CFileData.cFileName)!=0 &&
|
||
::strcmp("..", VO_CFileData.cFileName)!=0
|
||
);
|
||
//////////////////////
|
||
|
||
if(CB_IsTrue)
|
||
{
|
||
if(VR_CViewFile.OnDir(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewFile.OnDir(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
if(CB_IsTrue)*/
|
||
}
|
||
else // !VO_CFileData.IsDir()
|
||
{
|
||
if(VR_CViewFile.OnFile(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewFile.OnFile(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else // !VO_CFileData.IsDir()*/
|
||
|
||
VB_IsSearched = ::FindNextFile(VH_File, &VO_CFileData);
|
||
}/*
|
||
while(VB_IsSearched)*/
|
||
|
||
::FindClose(VH_File);
|
||
|
||
#else // !defined(_WIN)
|
||
|
||
ZCFileData VO_CFileData;
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
dirent VO_DirEnt;
|
||
#endif
|
||
dirent* VP_DirEnt;
|
||
TypeDirID VH_File= ::opendir(APC_DirPath);
|
||
char VCA_Search[_MAX_PATH2+1]={_T('0')};
|
||
|
||
if(VH_File==NULL)
|
||
return ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt= ::readdir(VH_File))!=0)
|
||
#endif
|
||
{
|
||
const bool CB_IsNotValid=(
|
||
::strcmp("." , VP_DirEnt->d_name)==0 ||
|
||
::strcmp("..", VP_DirEnt->d_name)==0
|
||
/*//////////*/ );
|
||
|
||
if(CB_IsNotValid) continue;
|
||
|
||
::strcpy(VCA_Search,APC_DirPath);
|
||
|
||
if(::strcmp(APC_DirPath, "/")!=0)
|
||
{ ::strcat(VCA_Search, "/"); }
|
||
|
||
::strcat(VCA_Search , VP_DirEnt->d_name);
|
||
::strcpy(VO_CFileData.cFileName, VP_DirEnt->d_name);
|
||
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)
|
||
{
|
||
throw ZCExceptDir
|
||
(
|
||
VP_DirEnt->d_name, "Fatal Error In "
|
||
"ZCDir::IterFile() : Can't know the file info"
|
||
);
|
||
/////////////////
|
||
|
||
return ZNsMain::ZNsEnum::ZERun_NO;
|
||
}/*
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)*/
|
||
|
||
if( VO_CFileData.IsDir() )
|
||
{
|
||
if(VR_CViewFile.OnDir (APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewFile.OnDir (APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}
|
||
else
|
||
{
|
||
if(VR_CViewFile.OnFile(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewFile.OnFile(APC_DirPath, VO_CFileData)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else*/
|
||
}/*
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt= ::readdir(VH_File))!=0)
|
||
#endif
|
||
*/
|
||
|
||
::closedir(VH_File);
|
||
|
||
if(VP_DirEnt==0)
|
||
return ZNsMain::ZNsEnum::ZERun_NO ;
|
||
|
||
#endif //!defined(_WIN)
|
||
|
||
return VE_ERun;
|
||
}/*
|
||
template<typename TViewFile> static ZNsMain::ZNsEnum::
|
||
ZERun IterFileEx(ZTypCPCh APC_DirPath, TViewFile AR_CViewFile) */
|
||
|
||
template<typename TViewFile, typename TTypeHelp>
|
||
static ZNsMain::ZNsEnum::ZERun IterFileEx
|
||
(ZTypCPCh APC_DirPath, TViewFile AR_CViewFile, TTypeHelp AR_CTypeHelp)
|
||
{
|
||
typedef typename ZNsMain::
|
||
ZtCTypeData<TViewFile>::TypeData TypeViewFile;
|
||
TypeViewFile& VR_CViewFile =
|
||
ZNsMain::ZtCTypeData<TViewFile>::GetObjRef(AR_CViewFile);
|
||
|
||
ZNsMain::ZNsEnum::ZERun VE_ERun= ZNsMain::ZNsEnum::ZERun_OK ;
|
||
|
||
if(APC_DirPath==0) return ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_WIN)
|
||
|
||
ZTypChar VCA_Search[_MAX_PATH2+1]={_T('0')};
|
||
|
||
::strcpy(VCA_Search, APC_DirPath);
|
||
::strcat(VCA_Search, "\\*.*" );
|
||
|
||
ZCFileData VO_CFileData ;
|
||
HANDLE VH_File =
|
||
::FindFirstFile(VCA_Search, &VO_CFileData);
|
||
BOOL VB_IsSearched = TRUE ;
|
||
|
||
if(VH_File==INVALID_HANDLE_VALUE)
|
||
return ZNsMain::ZNsEnum::ZERun_OK ;
|
||
|
||
while(VB_IsSearched)
|
||
{
|
||
if(VO_CFileData.IsDir()) // (VO_CFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||
{
|
||
const bool CB_IsTrue =
|
||
(
|
||
::strcmp("." , VO_CFileData.cFileName)!=0 &&
|
||
::strcmp("..", VO_CFileData.cFileName)!=0
|
||
);
|
||
//////////////////////
|
||
|
||
if(CB_IsTrue)
|
||
{
|
||
if(VR_CViewFile.template OnDir<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewFile.template OnDir<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
if(CB_IsTrue)*/
|
||
}
|
||
else
|
||
{
|
||
if(VR_CViewFile.template OnFile<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewFile.template OnFile<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else*/
|
||
|
||
VB_IsSearched = ::FindNextFile(VH_File, &VO_CFileData);
|
||
}/*
|
||
while(VB_IsSearched)*/
|
||
|
||
::FindClose(VH_File);
|
||
|
||
#else // !defined(_WIN)
|
||
|
||
ZCFileData VO_CFileData;
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
dirent VO_DirEnt;
|
||
#endif
|
||
dirent* VP_DirEnt;
|
||
TypeDirID VH_File= ::opendir(APC_DirPath);
|
||
char VCA_Search[_MAX_PATH2+1]={_T('0')};
|
||
|
||
if(VH_File==NULL) return ZNsMain::ZNsEnum::ZERun_OK;
|
||
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt = ::readdir(VH_File))!=0)
|
||
#endif
|
||
{
|
||
const bool CB_IsNotValid =
|
||
(
|
||
::strcmp(".", VP_DirEnt->d_name)==0 ||
|
||
::strcmp("..", VP_DirEnt->d_name)==0
|
||
);
|
||
//////////////////////////
|
||
|
||
if(CB_IsNotValid) continue;
|
||
|
||
::strcpy(VCA_Search,APC_DirPath);
|
||
|
||
if(::strcmp(APC_DirPath, "/")!=0)
|
||
{ ::strcat(VCA_Search, "/"); }
|
||
|
||
::strcat(VCA_Search , VP_DirEnt->d_name);
|
||
::strcpy(VO_CFileData.cFileName, VP_DirEnt->d_name);
|
||
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)
|
||
{
|
||
throw ZCExceptDir
|
||
(
|
||
VP_DirEnt->d_name, "Fatal Error In "
|
||
"ZCDir::IterFile() : Can't know the file info"
|
||
);
|
||
/////////////////
|
||
|
||
return ZNsMain::ZNsEnum::ZERun_NO;
|
||
}/*
|
||
if(::lstat(VCA_Search,&VO_CFileData)<0)*/
|
||
|
||
if( VO_CFileData.IsDir() )
|
||
{
|
||
if(VR_CViewFile.template OnDir <TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewFile.template OnDir <TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}
|
||
else
|
||
{
|
||
if(VR_CViewFile.template OnFile<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZNsMain::ZNsEnum::ZERun_NO)
|
||
{
|
||
VE_ERun=ZNsMain::ZNsEnum::ZERun_NO; break;
|
||
}/*
|
||
if(VR_CViewFile.template OnFile<TTypeHelp>
|
||
(APC_DirPath, VO_CFileData, AR_CTypeHelp)==ZNsMain::ZNsEnum::ZERun_NO)*/
|
||
}/*
|
||
else*/
|
||
}/*
|
||
#if defined(_REENTRANT) && !defined(_NO_USE_REEDDIR_R_)
|
||
while(::readdir_r(VH_File, &VO_DirEnt, &VP_DirEnt)==0 && VP_DirEnt!=0)
|
||
#else
|
||
while((VP_DirEnt = ::readdir(VH_File))!=0)
|
||
#endif
|
||
*/
|
||
|
||
::closedir(VH_File);
|
||
|
||
if(VP_DirEnt==0)
|
||
return ZNsMain::ZNsEnum::ZERun_NO ;
|
||
|
||
#endif // !defined(_WIN)
|
||
|
||
return VE_ERun;
|
||
}/*
|
||
template<typename TViewFile, typename TTypeHelp>
|
||
static ZNsMain::ZNsEnum::ZERun IterFileEx
|
||
(ZTypCPCh APC_DirPath, TViewFile AR_CViewFile, TTypeHelp AR_CTypeHelp)*/
|
||
|
||
|
||
template<typename TFileDataList> // TFileDataList 은 std::ZCFileData 의 리스트.
|
||
static void GetCFileDataList(ZTypCPCh APC_DirPath, TFileDataList& AR_TFileDataList)
|
||
{
|
||
/* APC_DirPath 디렉토리에 있는 파일만을 AR_TFileDataList 에 저장한다. 즉
|
||
APC_DirPath 의 하위 디렉토리로 찾아 들어가지 않는다. */
|
||
|
||
typedef ZNsMain::ZNsIFace::ZCViewFileDataList ZCViewFileDataList;
|
||
|
||
ZCViewFileDataList VO_CViewFileDataList; ////////////////////////
|
||
|
||
IterFileEx<ZCViewFileDataList, TFileDataList&>( /////////////////
|
||
APC_DirPath ,
|
||
VO_CViewFileDataList,
|
||
AR_TFileDataList
|
||
/*/////////*/ ); ////////////////////////////////////////////////
|
||
}/*
|
||
template<typename TFileDataList>
|
||
static void GetCFileDataList(ZTypCPCh APC_DirPath, TFileDataList& AR_TFileDataList) */
|
||
|
||
template<typename TFileDataList> // TFileDataList 은 ZCFileData 의 리스트.
|
||
static void GetCFileDataListRecur(ZTypCPCh APC_DirPath, TFileDataList& AR_TFileDataList)
|
||
{
|
||
/* APC_DirPath 디렉토리와 그 하위 디렉토리에 있는
|
||
모든 파일을 AR_TFileDataList 에 저장한다. */
|
||
|
||
typedef ZNsMain::ZNsIFace::ZCViewDirOfFileList ZCViewDirOfFileList;
|
||
|
||
ZCViewDirOfFileList VO_CViewDirOfFileList; ////////////////////////
|
||
|
||
IterDirEx<ZCViewDirOfFileList, TFileDataList&>( ///////////////////
|
||
APC_DirPath ,
|
||
VO_CViewDirOfFileList,
|
||
AR_TFileDataList
|
||
/*/////////*/ ); //////////////////////////////////////////////////
|
||
}/*
|
||
template<typename TFileDataList>
|
||
static void GetCFileDataListRecur(ZTypCPCh APC_DirPath, TFileDataList& AR_TFileDataList) */
|
||
|
||
|
||
template<typename TDirNameList> // TDirNameList 은 문자열 리스트.
|
||
static void GetDirNameList(ZTypCPCh APC_DirPath, TDirNameList& ARR_CDirNameList)
|
||
{
|
||
/* APC_DirPath 의 바로 밑에 있는 하위 디렉토리만 찾는다.
|
||
즉 재귀적으로 하위 디렉토리를 찾지 않는다. */
|
||
|
||
typedef ZNsMain::ZNsIFace::ZCViewFileOfDir ZCViewFileOfDir;
|
||
|
||
ZCViewFileOfDir VO_CViewDirList; //////////////////////////
|
||
|
||
IterFileEx<ZCViewFileOfDir, TDirNameList&>( ///////////////
|
||
APC_DirPath ,
|
||
VO_CViewDirList,
|
||
ARR_CDirNameList
|
||
/*/////////*/ ); //////////////////////////////////////////
|
||
}/*
|
||
template<typename TDirNameList>
|
||
static void GetDirNameList(ZTypCPCh APC_DirPath, TDirNameList& ARR_CDirNameList) */
|
||
|
||
|
||
#ifdef _WIN
|
||
|
||
|
||
// 비어있는 디렉토리를 삭제
|
||
|
||
static bool RemoveEmptyDir(ZTypCPCh APC_PathName)
|
||
{
|
||
return ::RemoveDirectoryA(APC_PathName)==TRUE ;
|
||
}/*
|
||
static bool RemoveEmptyDir(ZTypCPCh APC_PathName)*/
|
||
|
||
static bool MakeDir(ZTypCPCh APC_PathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes=NULL)
|
||
{
|
||
return ::CreateDirectoryA(APC_PathName, lpSecurityAttributes)==TRUE ;
|
||
}/*
|
||
static bool MakeDir(ZTypCPCh APC_PathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes=NULL)*/
|
||
|
||
template<typename TString> static bool
|
||
GetNowDir(TString& ARR_CStringDir, bool AB_DoKeepPrev=false)
|
||
{
|
||
// 디렉토리명이 _MAX_DIR 을 넘을 수 있다. 그래서 넉넉하게 곱하기 4 를 한다.
|
||
|
||
if(false==AB_DoKeepPrev)
|
||
{
|
||
ZTycInt CI_BuffSize = _MAX_DIR*4 ;
|
||
|
||
ARR_CStringDir.resize(CI_BuffSize+1, ' ');
|
||
|
||
// ::GetCurrentDirectory() 는 완전 경로를 얻고 그 길이를 반환한다.
|
||
|
||
long VL_Length = ::GetCurrentDirectoryA
|
||
( CI_BuffSize, (ZTypPCh)ARR_CStringDir.data() );
|
||
|
||
if(VL_Length<1){ return false; } //////
|
||
|
||
ARR_CStringDir.resize(VL_Length, ' '); return true ;
|
||
}/*
|
||
if(false==AB_DoKeepPrev)*/
|
||
|
||
|
||
ZTypLength VL_PrevSize = ARR_CStringDir.size() ;
|
||
ZTycInt CI_BuffSize = VL_PrevSize+_MAX_DIR*4 ;
|
||
ARR_CStringDir.resize(CI_BuffSize+1, ' ') ;
|
||
ZTypPChar VP_CopyStart =
|
||
(ZTypPChar)ARR_CStringDir.data()+VL_PrevSize ;
|
||
|
||
// ::GetCurrentDirectory() 는 완전 경로를 얻고 그 길이를 반환한다.
|
||
|
||
long VL_Length =
|
||
::GetCurrentDirectoryA(CI_BuffSize, VP_CopyStart);
|
||
|
||
if(VL_Length<1) return false; //////////
|
||
|
||
ARR_CStringDir.
|
||
resize(VL_PrevSize+VL_Length, ' ' );
|
||
return true ;
|
||
}/*
|
||
template<typename TString> static bool
|
||
GetNowDir(TString& ARR_CStringDir, bool AB_DoKeepPrev=false) */
|
||
|
||
static bool ChangeDir(ZTypCPCh APC_DirName)
|
||
{
|
||
return ::SetCurrentDirectoryA(APC_DirName)==TRUE ;
|
||
}/*
|
||
static bool ChangeDir(ZTypCPCh APC_DirName)*/
|
||
|
||
#else //!defined(_WIN)
|
||
|
||
static bool RemoveEmptyDir(const char* APC_PathName)
|
||
{
|
||
return ::rmdir(APC_PathName)==0 ; // 비어있는 디렉토리를 삭제
|
||
}/*
|
||
static bool RemoveEmptyDir(const char* APC_PathName)*/
|
||
|
||
static bool MakeDir(const char* APC_PathName, mode_t mode=0744)
|
||
{
|
||
return ::mkdir(APC_PathName, mode)==0 ;
|
||
}/*
|
||
static bool MakeDir(const char* APC_PathName, mode_t mode=0744)*/
|
||
|
||
template<typename TString> static bool
|
||
GetNowDir(TString& ARR_CStringDir, bool AB_DoKeepPrev=false)
|
||
{
|
||
if(false==AB_DoKeepPrev)
|
||
{
|
||
ZTycInt CI_BuffSize = _MAX_DIR*4 ;
|
||
|
||
ARR_CStringDir.resize(CI_BuffSize+1, ' ');
|
||
|
||
char* VP_NowDir = ::getcwd
|
||
((char*)ARR_CStringDir.data(), CI_BuffSize);
|
||
|
||
if(VP_NowDir==0){return false;} ARR_CStringDir.
|
||
|
||
resize(ZNsMain::ZftLength(VP_NowDir), ' ') ;
|
||
|
||
return true; /*********************************/
|
||
}/*
|
||
if(false==AB_DoKeepPrev)*/
|
||
|
||
|
||
ZTypLength VL_PrevSize = ARR_CStringDir.size() ;
|
||
ZTycInt CI_BuffSize = VL_PrevSize+_MAX_DIR*4 ;
|
||
ARR_CStringDir.resize(CI_BuffSize+1, ' ') ;
|
||
ZTypPChar VP_CopyStart =
|
||
(ZTypPChar)ARR_CStringDir.data()+VL_PrevSize ;
|
||
|
||
char* VP_NowDir = ::getcwd(VP_CopyStart, CI_BuffSize);
|
||
|
||
if(VP_NowDir==0) return false; ////////////////////
|
||
|
||
ARR_CStringDir.
|
||
resize( VL_PrevSize+ZftLength(VP_NowDir), ' ');
|
||
return true ;
|
||
}/*
|
||
template<typename TString> static bool
|
||
GetNowDir(TString& ARR_CStringDir, bool AB_DoKeepPrev=false) */
|
||
|
||
static bool ChangeDir(const char* APC_DirName)
|
||
{
|
||
return ::chdir(APC_DirName)==0 ;
|
||
}/*
|
||
static bool ChangeDir(const char* APC_DirName)*/
|
||
|
||
#endif //!defined(_WIN)
|
||
|
||
|
||
/*/////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ 절대 경로 AP_AbsPath 에 대해서, 기준 경로 AP_StdPath 에 로부터의 상대 경로를 구한다.
|
||
즉 현재 디렉토리 위치가 기준 경로 AP_StdPath 라 가정했을 때, 이 경로에서 절대 경로
|
||
AP_AbsPath 에 이르는 상대 경로를 구하는 것이다.
|
||
|
||
두 경로 모두 디렉토리 구분자로 끝나는 것이 일관성이 있어서 좋을 것 같다. 이렇게 하면
|
||
AP_StdPath 와 GetRelativePath() 함수로 얻어진 상대 경로를 더하면, 바로 AP_AbsPath 경
|
||
로에 이를 수 있다.
|
||
|
||
■ 기준경로 AP_StdPath 도 절대경로로 입력받는다.
|
||
|
||
■ 반환 경로에는 디렉토리 구분자가 붙는다.
|
||
|
||
■ 경로명에 디렉토리 구분자가 연이어 존재해서는 안된다.
|
||
이에 대한 에러 처리는 넣지 않았다.
|
||
|
||
■ 예제 코드
|
||
|
||
const char* CPC_AbsPath="C:\\Windows\\A\\B\\";
|
||
const char* CPC_StdPath="C:\\Windows\\A\\C\\D\\";
|
||
|
||
std::string VO_CStringRelativePath;
|
||
|
||
std::ZCDir::GetRelativePath
|
||
(
|
||
CPC_AbsPath, strlen(CPC_AbsPath),
|
||
CPC_StdPath, strlen(CPC_StdPath), RR(VO_CStringRelativePath)
|
||
);
|
||
|
||
cout<<"RelativePath="<<VO_CStringRelativePath.c_str()<<endl;
|
||
|
||
■ 예제 코드의 결과 값은 RelativePath=..\..\B\ 이어야 한다.
|
||
|
||
/////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
template<typename TString, typename TTypChar> static TString& GetRelativePath
|
||
(
|
||
const TTypChar* AP_AbsPath, ZTypLength AI_AbsPathLen,
|
||
const TTypChar* AP_StdPath, ZTypLength AI_StdPathLen,
|
||
TString& ARR_CStrRelativePath
|
||
)
|
||
/*#########################################################################*/
|
||
{
|
||
/* 맨 끝에 디렉토리 구분자가 있다면, 길이를 1 줄이는 것으로 무효화시킨다. */
|
||
|
||
const bool CB_IsTrue = ( /*###########################*/
|
||
AI_AbsPathLen>0 &&
|
||
(
|
||
AP_AbsPath[AI_AbsPathLen-1]=='\\' ||
|
||
AP_AbsPath[AI_AbsPathLen-1]=='/'
|
||
)
|
||
/*########*/ ); /*####################################*/
|
||
|
||
if(CB_IsTrue){ --AI_AbsPathLen; }
|
||
|
||
const bool CB_IsTrue2 = ( /*##########################*/
|
||
AI_StdPathLen>0 &&
|
||
(
|
||
AP_StdPath[AI_StdPathLen-1]=='\\' ||
|
||
AP_StdPath[AI_StdPathLen-1]=='/'
|
||
)
|
||
/*#########*/); /*####################################*/
|
||
|
||
if(CB_IsTrue2){ --AI_StdPathLen; }
|
||
|
||
if(AI_AbsPathLen<1)
|
||
{
|
||
return ARR_CStrRelativePath="" ;
|
||
}
|
||
if(AI_StdPathLen<1)
|
||
{
|
||
ARR_CStrRelativePath="";
|
||
ARR_CStrRelativePath.append(AP_AbsPath, AI_AbsPathLen);
|
||
|
||
#ifdef _WIN
|
||
ARR_CStrRelativePath+="\\";
|
||
#else
|
||
ARR_CStrRelativePath+="/";
|
||
#endif
|
||
|
||
return ARR_CStrRelativePath;
|
||
}/*
|
||
if(AI_StdPathLen<1)*/
|
||
|
||
ZTypLength VI_MinLoop =
|
||
( AI_AbsPathLen>=AI_StdPathLen ? AI_StdPathLen : AI_AbsPathLen ) ;
|
||
|
||
const char* VP_AbsPath=AP_AbsPath ;
|
||
const char* VP_StdPath=AP_StdPath ;
|
||
char VC_Temp = char(0) ;
|
||
|
||
ZTypLength VI_EqualCnt = 0; // 앞에서부터 일치하는 문자열 갯수
|
||
ZTypLength VI_LastDirPos=-1; // 앞에서부터 일치하는 문자열 중 마지막 디렉토리 구분자의 위치
|
||
|
||
while(VI_EqualCnt<VI_MinLoop)
|
||
{
|
||
if((VC_Temp= *VP_AbsPath)!= *VP_StdPath) break;
|
||
|
||
if(VC_Temp=='\\' || VC_Temp=='/')
|
||
{
|
||
VI_LastDirPos=VI_EqualCnt;
|
||
}/*
|
||
if(VC_Temp=='\\' || VC_Temp=='/')*/
|
||
|
||
++VP_AbsPath ;
|
||
++VP_StdPath ;
|
||
++VI_EqualCnt;
|
||
}/*
|
||
while(VI_EqualCnt<VI_MinLoop)*/
|
||
|
||
if(VI_EqualCnt==VI_MinLoop)
|
||
{
|
||
VI_LastDirPos=VI_EqualCnt;
|
||
}
|
||
if(VI_EqualCnt<1 || VI_LastDirPos<1)
|
||
{
|
||
ARR_CStrRelativePath="";
|
||
ARR_CStrRelativePath.append(AP_AbsPath,AI_AbsPathLen);
|
||
|
||
#ifdef _WIN
|
||
ARR_CStrRelativePath+="\\";
|
||
#else
|
||
ARR_CStrRelativePath+="/";
|
||
#endif
|
||
|
||
return ARR_CStrRelativePath;
|
||
}/*
|
||
if(VI_EqualCnt<1 || VI_LastDirPos<1)*/
|
||
|
||
VP_AbsPath=AP_AbsPath+VI_LastDirPos+1;
|
||
VP_StdPath=AP_StdPath+VI_LastDirPos+1;
|
||
|
||
AI_AbsPathLen-=VI_LastDirPos+1;
|
||
AI_StdPathLen-=VI_LastDirPos+1;
|
||
|
||
if(AI_AbsPathLen<1 && AI_StdPathLen<1)
|
||
{
|
||
return ARR_CStrRelativePath="";
|
||
}
|
||
else if(AI_AbsPathLen<1)
|
||
{
|
||
ARR_CStrRelativePath="";
|
||
|
||
ZTypLength VI_DirCnt=1; ZTypLength i=0;
|
||
const char* VP_Temp=VP_StdPath;
|
||
|
||
for(; i<AI_StdPathLen; ++i)
|
||
{
|
||
if((VC_Temp=*VP_Temp++)=='\\' || VC_Temp=='/') ++VI_DirCnt;
|
||
}/*
|
||
for(; i<AI_StdPathLen; ++i)*/
|
||
|
||
for(i=0; i<VI_DirCnt; ++i)
|
||
{
|
||
#ifdef _WIN
|
||
ARR_CStrRelativePath+="..\\";
|
||
#else
|
||
ARR_CStrRelativePath+="../";
|
||
#endif
|
||
}/*
|
||
for(i=0; i<VI_DirCnt; ++i)*/
|
||
|
||
return ARR_CStrRelativePath;
|
||
}/*
|
||
else if(AI_AbsPathLen<1)*/
|
||
else if(AI_StdPathLen<1)
|
||
{
|
||
ARR_CStrRelativePath="";
|
||
ARR_CStrRelativePath.append(VP_AbsPath, AI_AbsPathLen);
|
||
|
||
#ifdef _WIN
|
||
ARR_CStrRelativePath+="\\";
|
||
#else
|
||
ARR_CStrRelativePath+="/";
|
||
#endif
|
||
|
||
return ARR_CStrRelativePath;
|
||
}/*
|
||
else if(AI_StdPathLen<1)*/
|
||
|
||
ARR_CStrRelativePath="";
|
||
|
||
ZTypLength VI_DirCnt =1 ;
|
||
ZTypLength i =0 ;
|
||
const char* VP_Temp =VP_StdPath;
|
||
|
||
for(; i<AI_StdPathLen; ++i)
|
||
{
|
||
if((VC_Temp=*VP_Temp++)=='\\' || VC_Temp=='/') ++VI_DirCnt;
|
||
}/*
|
||
for(; i<AI_StdPathLen; ++i)*/
|
||
|
||
for(i=0; i<VI_DirCnt; ++i)
|
||
{
|
||
#ifdef _WIN
|
||
ARR_CStrRelativePath+="..\\";
|
||
#else
|
||
ARR_CStrRelativePath+="../";
|
||
#endif
|
||
}/*
|
||
for(i=0; i<VI_DirCnt; ++i)*/
|
||
|
||
ARR_CStrRelativePath.append(VP_AbsPath, AI_AbsPathLen);
|
||
|
||
#ifdef _WIN
|
||
ARR_CStrRelativePath+="\\";
|
||
#else
|
||
ARR_CStrRelativePath+="/";
|
||
#endif
|
||
|
||
return ARR_CStrRelativePath;
|
||
}/*
|
||
template<typename TString, typename TTypChar> static TString& GetRelativePath
|
||
(
|
||
const TTypChar* AP_AbsPath, ZTypLength AI_AbsPathLen,
|
||
const TTypChar* AP_StdPath, ZTypLength AI_StdPathLen,
|
||
TString& ARR_CStrRelativePath
|
||
)
|
||
###########################################################################*/
|
||
|
||
template<typename TString, typename TTypChar> /*###########################*/
|
||
static TString& GetRelativePath
|
||
(
|
||
const TTypChar* AP_AbsPath,
|
||
const TTypChar* AP_StdPath,
|
||
TString& ARR_CStrRelativePath
|
||
)
|
||
/*#########################################################################*/
|
||
{
|
||
using ZNsMain::ZftLength ;
|
||
|
||
return GetRelativePath( ///////////////////////////
|
||
AP_AbsPath ,
|
||
ZftLength(AP_AbsPath) ,
|
||
AP_StdPath ,
|
||
ZftLength(AP_StdPath) ,
|
||
RR(ARR_CStrRelativePath)
|
||
/*/////////*/ ); //////////////////////////////////
|
||
}/*
|
||
template<typename TString, typename TTypChar> ###############################
|
||
static TString& GetRelativePath
|
||
(
|
||
const TTypChar* AP_AbsPath,
|
||
const TTypChar* AP_StdPath,
|
||
TString& ARR_CStrRelativePath
|
||
)
|
||
###########################################################################*/
|
||
|
||
static std::string GetRelativePath(
|
||
const char* AP_AbsPath, ZTypLength AI_AbsPathLen, const char* AP_StdPath, ZTypLength AI_StdPathLen)
|
||
{
|
||
static std::string SO_CStrRelativePath;
|
||
|
||
return GetRelativePath( ///////////////////////////
|
||
AP_AbsPath , AI_AbsPathLen ,
|
||
AP_StdPath , AI_StdPathLen ,
|
||
RR(SO_CStrRelativePath)
|
||
/*/////////*/ ); //////////////////////////////////
|
||
}/*
|
||
static std::string GetRelativePath(
|
||
const char* AP_AbsPath, ZTypLength AI_AbsPathLen, const char* AP_StdPath, ZTypLength AI_StdPathLen) */
|
||
|
||
static std::string GetRelativePath(const char* AP_AbsPath, const char* AP_StdPath)
|
||
{
|
||
using ZNsMain::ZftLength; static std::string SO_CStrRelativePath;
|
||
|
||
return GetRelativePath ///////////////////////////////
|
||
(
|
||
AP_AbsPath , ZftLength(AP_AbsPath) ,
|
||
AP_StdPath , ZftLength(AP_StdPath) ,
|
||
RR(SO_CStrRelativePath)
|
||
);
|
||
///////////////////////////////////////////////////////
|
||
}/*
|
||
static std::string GetRelativePath(const char* AP_AbsPath, const char* AP_StdPath) */
|
||
|
||
#if defined(_WIN)
|
||
|
||
static bool DeleteFile(ZTypCPCh APC_FileName)
|
||
{
|
||
return ::DeleteFileA(APC_FileName)==TRUE;
|
||
}/*
|
||
static bool DeleteFile(ZTypCPCh APC_FileName)*/
|
||
|
||
static bool MoveFile(ZTypCPCh APC_FileNow, ZTypCPCh APC_FileNew)
|
||
{
|
||
return ::MoveFileA(APC_FileNow, APC_FileNew)==TRUE;
|
||
}/*
|
||
static bool MoveFile(ZTypCPCh APC_FileNow, ZTypCPCh APC_FileNew)*/
|
||
|
||
#else //!defined(_WIN)
|
||
|
||
static bool DeleteFile(const char* APC_FileName)
|
||
{
|
||
return ::unlink(APC_FileName)==0;
|
||
}/*
|
||
static bool DeleteFile(const char* APC_FileName)*/
|
||
|
||
static bool MoveFile(const char* APC_FileNow, const char* APC_FileNew)
|
||
{
|
||
return ::rename(APC_FileNow, APC_FileNew)==0;
|
||
}/*
|
||
static bool MoveFile(const char* APC_FileNow, const char* APC_FileNew)*/
|
||
|
||
#endif // !defined(_WIN)
|
||
|
||
|
||
public:
|
||
};/*
|
||
class ZCDir*/
|
||
|
||
#ifdef _WIN
|
||
static int GetLastErrorNo(){return ::WSAGetLastError();}
|
||
#else
|
||
static int GetLastErrorNo(){return errno ;}
|
||
#endif
|
||
|
||
|
||
#ifdef __linux__
|
||
|
||
|
||
/* 비동기 입출력은 완료시 콜백할 수 있는 윈도우 쪽이 편한 듯 하다.
|
||
리눅스도 signal 을 등록하면 물론 가능하다. cf) lio_listio() */
|
||
|
||
|
||
/*//////////////////////////////////////////////////////////////
|
||
|
||
struct aiocb
|
||
{
|
||
int aio_fildes; // File desriptor.
|
||
int aio_lio_opcode; // Operation to be performed.
|
||
int aio_reqprio; // Request priority offset.
|
||
volatile void *aio_buf; // Location of buffer.
|
||
size_t aio_nbytes; // Length of transfer.
|
||
struct sigevent aio_sigevent; // Signal number and value.
|
||
|
||
Internal members.
|
||
|
||
struct aiocb *__next_prio;
|
||
int __abs_prio;
|
||
int __policy;
|
||
int __error_code;
|
||
__ssize_t __return_value;
|
||
|
||
#ifndef __USE_FILE_OFFSET64
|
||
__off_t aio_offset; // File offset.
|
||
char __pad[sizeof (__off64_t) - sizeof (__off_t)];
|
||
#else
|
||
__off64_t aio_offset; // File offset.
|
||
#endif
|
||
char __unused[32];
|
||
};
|
||
|
||
//////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
class ZCAsynIO : public aiocb
|
||
{
|
||
public :
|
||
|
||
ZCAsynIO()
|
||
{
|
||
::memset(this, 0, sizeof(aiocb));
|
||
}/*
|
||
ZCAsynIO()*/
|
||
|
||
void SetHandle(int AI_FileHandle)
|
||
{
|
||
this->aio_fildes=AI_FileHandle;
|
||
}/*
|
||
void SetHandle(int AI_FileHandle)*/
|
||
|
||
void Init(int AI_FileHandle, ZNsMain::ZTypLong ALL_Offset=0)
|
||
{
|
||
this->aio_fildes=AI_FileHandle;
|
||
this->aio_offset=ALL_Offset ;
|
||
}/*
|
||
void Init(int AI_FileHandle, ZNsMain::ZTypLong ALL_Offset=0)*/
|
||
|
||
int Read(volatile char* AP_Buffer, int AI_BufSize)
|
||
{
|
||
this->aio_buf =AP_Buffer ;
|
||
this->aio_nbytes=AI_BufSize ;
|
||
|
||
return ::aio_read(this);
|
||
}/*
|
||
int Read(volatile char* AP_Buffer, int AI_BufSize)*/
|
||
|
||
int Write(volatile char* AP_Buffer, int AI_BufSize)
|
||
{
|
||
this->aio_buf =AP_Buffer ;
|
||
this->aio_nbytes=AI_BufSize ;
|
||
|
||
return ::aio_write(this);
|
||
}/*
|
||
int Write(volatile char* AP_Buffer, int AI_BufSize)*/
|
||
|
||
int GetErrCode()
|
||
{
|
||
return ::aio_error(this);
|
||
}/*
|
||
int GetErrCode()*/
|
||
|
||
|
||
/*/////////////////////////////////////////////////////////////////////
|
||
|
||
■ aio_return(struct aiocb*)
|
||
|
||
RETURN VALUE
|
||
|
||
If the asynchronous I/O operation has completed, this function returns
|
||
the value that would have been returned in case of a synchronous read,
|
||
write, or fsync request. Otherwise the return value is undefined. On
|
||
error, the error value is returned.
|
||
|
||
/////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
ssize_t GetFinishResult()
|
||
{
|
||
return ::aio_return(this) ;
|
||
}/*
|
||
ssize_t GetFinishResult()*/
|
||
|
||
|
||
// Windows 와 호환을 위해...
|
||
|
||
void GetFinishResult(ssize_t& ARRI_FinishCode)
|
||
{
|
||
ARRI_FinishCode = ::aio_return(this) ;
|
||
}/*
|
||
void GetFinishResult(ssize_t& ARRI_FinishCode)*/
|
||
|
||
|
||
/*/////////////////////////////////////////////////////////////////////////
|
||
|
||
■ aio_cancel(int fd,struct aiocb*)
|
||
|
||
RETURN VALUE
|
||
|
||
This function returns AIO_CANCELED if all requests were successfully
|
||
cancelled. It returns AIO_NOTCANCELED when at least one of the requests
|
||
specified was not cancelled because it was in progress. In this case
|
||
one may check the status of individual requests using aio_error(3).
|
||
This function returns AIO_ALLDONE when all requests had been completed
|
||
already before this call. When some error occurs, -1 is returned, and
|
||
errno is set appropriately.
|
||
|
||
■ Return values of cancelation function.
|
||
|
||
enum
|
||
{
|
||
AIO_CANCELED,
|
||
#define AIO_CANCELED AIO_CANCELED
|
||
AIO_NOTCANCELED,
|
||
#define AIO_NOTCANCELED AIO_NOTCANCELED
|
||
AIO_ALLDONE
|
||
#define AIO_ALLDONE AIO_ALLDONE
|
||
};
|
||
|
||
/////////////////////////////////////////////////////////////////////////*/
|
||
|
||
int Cancel()
|
||
{
|
||
return ::aio_cancel(this->aio_fildes, this) ;
|
||
}/*
|
||
int Cancel()*/
|
||
|
||
int Cancel(int AI_FileDesc)
|
||
{
|
||
return ::aio_cancel(AI_FileDesc, this) ;
|
||
}/*
|
||
int Cancel(int AI_FileDesc)*/
|
||
|
||
|
||
/*/////////////////////////////////////////////////////////////////////////
|
||
|
||
■ aio_fsync(int op,struct aiocb*);
|
||
|
||
** DESCRIPTION
|
||
|
||
The aio_fsync function does a sync on all outstanding asynchronous I/O
|
||
operations associated with aiocbp->aio_fildes.
|
||
|
||
More precisely, if op is O_SYNC, then all currently queued I/O opera-
|
||
tions shall be completed as if by a call of fsync(2), and if op is
|
||
O_DSYNC, this call is the asynchronous analog of fdatasync(2). Note
|
||
that this is a request only - this call does not wait for I/O comple-
|
||
tion.
|
||
|
||
Apart from aio_fildes the only field in the structure pointed to by
|
||
aiocbp that is used by this call is the aio_sigevent field (a struct
|
||
sigevent) that indicates the desired type of asynchronous notification
|
||
at completion. All other fields are ignored.
|
||
|
||
** RETURN VALUE
|
||
|
||
On success (the sync request was successfully queued) this function
|
||
returns 0. On error -1 is returned, and errno is set appropriately.
|
||
|
||
|
||
** Operation codes for `aio_lio_opcode'.
|
||
|
||
enum
|
||
{
|
||
LIO_READ,
|
||
#define LIO_READ LIO_READ
|
||
LIO_WRITE,
|
||
#define LIO_WRITE LIO_WRITE
|
||
LIO_NOP
|
||
#define LIO_NOP LIO_NOP
|
||
};
|
||
|
||
/////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
bool FSync(int AI_Operation)
|
||
{
|
||
return ::aio_fsync(AI_Operation, this)==0 ;
|
||
}/*
|
||
bool FSync(int AI_Operation)*/
|
||
|
||
|
||
/*/////////////////////////////////////////////////////////////////////////
|
||
|
||
■ int aio_suspend(const struct aiocb * const cblist[],int n, const struct timespec *timeout);
|
||
|
||
** DESCRIPTION
|
||
|
||
The aio_suspend function suspends the calling process until at least
|
||
one of the asynchronous I/O requests in the list cblist of length n
|
||
have completed, a signal is delivered, or timeout is not NULL and the
|
||
time interval it indicates has passed.
|
||
|
||
Each item in the list must either be NULL (and then is ignored), or a
|
||
pointer to a control block on which I/O was initiated using
|
||
aio_read(3), aio_write(3), or lio_listio(3).
|
||
|
||
If CLOCK_MONOTONIC is supported, this clock is used to measure the
|
||
timeout interval.
|
||
|
||
** RETURN VALUE
|
||
|
||
If this function returns after completion of one of the indicated
|
||
requests, it returns 0. Otherwise it returns -1 and sets errno appro-
|
||
priately.
|
||
|
||
/////////////////////////////////////////////////////////////////////////*/
|
||
|
||
bool Suspend(const struct timespec* AP_TimeOut)
|
||
{
|
||
aiocb* VP_AIOCB[1]; VP_AIOCB[0]=this;
|
||
|
||
return ::aio_suspend(VP_AIOCB, 1/*VP_AIOCB 원소수*/, AP_TimeOut)==0 ;
|
||
}/*
|
||
bool Suspend(const struct timespec* AP_TimeOut)*/
|
||
|
||
static bool Suspend(const struct aiocb* const APA_AIOCB[], int AI_Size, const struct timespec* AP_TimeOut)
|
||
{
|
||
return ::aio_suspend(APA_AIOCB, AI_Size, AP_TimeOut)==0 ;
|
||
}/*
|
||
static bool Suspend(const struct aiocb* const APA_AIOCB[], int AI_Size, const struct timespec* AP_TimeOut)*/
|
||
|
||
|
||
/*////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ 윈도우의 WaitForMultipleObjects() 과 비슷한 POSIX 함수는 lio_listio() 이다.
|
||
|
||
DWORD WaitForMultipleObjects
|
||
(
|
||
DWORD nCount,
|
||
CONST HANDLE* lpHandles,
|
||
BOOL fWaitAll,
|
||
DWORD dwMilliseconds
|
||
);
|
||
|
||
DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds );
|
||
|
||
enum
|
||
{
|
||
LIO_WAIT,
|
||
#define LIO_WAIT LIO_WAIT
|
||
LIO_NOWAIT
|
||
#define LIO_NOWAIT LIO_NOWAIT
|
||
};
|
||
|
||
|
||
int lio_listio
|
||
(
|
||
int mode,
|
||
struct aiocb *restrict const list[restrict],
|
||
int nent,
|
||
struct sigevent *restrict sig
|
||
);
|
||
|
||
////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
public:
|
||
};/*
|
||
class ZCAsynIO : public aiocb*/
|
||
|
||
|
||
#elif defined(_WIN)
|
||
|
||
|
||
/*//////////////////////////////////////////////////////////////////////////////
|
||
|
||
typedef struct _OVERLAPPED
|
||
{
|
||
ULONG_PTR Internal;
|
||
ULONG_PTR InternalHigh;
|
||
union
|
||
{
|
||
struct
|
||
{
|
||
DWORD Offset;
|
||
DWORD OffsetHigh;
|
||
};
|
||
|
||
PVOID Pointer;
|
||
}; HANDLE hEvent;
|
||
} OVERLAPPED, *LPOVERLAPPED;
|
||
|
||
Internal
|
||
Reserved for operating system use.
|
||
This member, which specifies a system-dependent status,
|
||
is valid when the GetOverlappedResult function returns
|
||
without setting the extended error information to ERROR_IO_PENDING.
|
||
|
||
InternalHigh
|
||
Reserved for operating system use.
|
||
This member, which specifies the length of the data transferred,
|
||
is valid when the GetOverlappedResult function returns TRUE.
|
||
|
||
Offset
|
||
File position at which to start the transfer.
|
||
The file position is a byte offset from the start of the file.
|
||
The calling process must set this member before calling the ReadFile or WriteFile function.
|
||
This member is used only when the device is a file. Otherwise, this member must be zero.
|
||
|
||
OffsetHigh
|
||
High-order word of the file position at which to start the transfer.
|
||
This member is used only when the device is a file.
|
||
Otherwise, this member must be zero.
|
||
|
||
Pointer
|
||
Reserved for system use; do not use.
|
||
|
||
hEvent
|
||
Handle to an event that will be set to the signaled state
|
||
when the operation has been completed.
|
||
The calling process must set this member either to zero or a valid event handle
|
||
before calling any overlapped functions.
|
||
To create an event object,
|
||
use the CreateEvent function.
|
||
This function returns a handle that can be used to synchronize simultaneous I/O requests for a device.
|
||
Functions such as ReadFile and WriteFile set this handle to the nonsignaled state
|
||
before they begin an I/O operation.
|
||
When the operation has completed, the handle is set to the signaled state.
|
||
|
||
Functions such as GetOverlappedResult and the wait functions reset auto-reset events to the nonsignaled state.
|
||
Therefore, if you use an auto-reset event,
|
||
your application can hang if you wait for the operation to complete then call GetOverlappedResult
|
||
|
||
|
||
BOOL ReadFileEx
|
||
(
|
||
HANDLE hFile,
|
||
LPVOID lpBuffer,
|
||
DWORD nNumberOfBytesToRead,
|
||
LPOVERLAPPED lpOverlapped,
|
||
LPOVERLAPPED_COMPLETION_ROUTINE APF_CompletionRoutine
|
||
);
|
||
|
||
BOOL WriteFileEx
|
||
(
|
||
HANDLE hFile,
|
||
LPCVOID lpBuffer,
|
||
DWORD nNumberOfBytesToWrite,
|
||
LPOVERLAPPED lpOverlapped,
|
||
LPOVERLAPPED_COMPLETION_ROUTINE APF_CompletionRoutine
|
||
);
|
||
|
||
VOID CALLBACK FileIOCompletionRoutine
|
||
(
|
||
DWORD dwErrorCode,
|
||
DWORD dwNumberOfBytesTransfered,
|
||
LPOVERLAPPED lpOverlapped
|
||
);
|
||
|
||
//////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
class ZCAsynIO : public OVERLAPPED
|
||
{
|
||
private:
|
||
HANDLE mh_Handle;
|
||
public :
|
||
|
||
ZCAsynIO(HANDLE AH_FileHandle=INVALID_HANDLE_VALUE, DWORD AI_Offset=0, DWORD AI_OffseHigh=0, HANDLE AH_Event=NULL)
|
||
{
|
||
this->mh_Handle =AH_FileHandle;
|
||
this->Offset =AI_Offset ;
|
||
this->OffsetHigh=AI_OffseHigh ;
|
||
this->hEvent =AH_Event ;
|
||
}/*
|
||
ZCAsynIO(HANDLE AH_FileHandle=INVALID_HANDLE_VALUE, DWORD AI_Offset=0, DWORD AI_OffseHigh=0, HANDLE AH_Event=NULL)*/
|
||
|
||
void SetHandle(HANDLE AH_FileHandle)
|
||
{
|
||
mh_Handle=AH_FileHandle ;
|
||
}/*
|
||
void SetHandle(AH_FileHandle)*/
|
||
|
||
void Init(HANDLE AH_FileHandle, DWORD AI_Offset=0, DWORD AI_OffseHigh=0, HANDLE AH_Event=NULL)
|
||
{
|
||
this->mh_Handle =AH_FileHandle;
|
||
this->Offset =AI_Offset ;
|
||
this->OffsetHigh=AI_OffseHigh ;
|
||
this->hEvent =AH_Event ;
|
||
}/*
|
||
void Init(HANDLE AH_FileHandle, DWORD AI_Offset=0, DWORD AI_OffseHigh=0, HANDLE AH_Event=NULL)*/
|
||
|
||
DWORD Read(LPVOID AP_Buffer, DWORD AI_BufferSize)
|
||
{
|
||
DWORD VDW_ReadSize=0; ::ReadFile( //////////
|
||
mh_Handle ,
|
||
AP_Buffer ,
|
||
AI_BufferSize ,
|
||
&VDW_ReadSize ,
|
||
this
|
||
/*/////////*/ ); ///////////////////////////
|
||
|
||
return VDW_ReadSize;
|
||
}/*
|
||
DWORD Read(LPVOID AP_Buffer, DWORD AI_BufferSize)*/
|
||
|
||
BOOL Read(LPVOID AP_Buffer, DWORD AI_BufferSize, DWORD& ARR_ReadSize)
|
||
{
|
||
return ::ReadFile(mh_Handle, AP_Buffer, AI_BufferSize, &ARR_ReadSize, this);
|
||
}/*
|
||
BOOL Read(LPVOID AP_Buffer, DWORD AI_BufferSize, DWORD& ARR_ReadSize)*/
|
||
|
||
BOOL Read(LPVOID AP_Buffer, DWORD AI_BufferSize, LPOVERLAPPED_COMPLETION_ROUTINE APF_CompletionRoutine)
|
||
{
|
||
return ::ReadFileEx(mh_Handle,AP_Buffer, AI_BufferSize, this, APF_CompletionRoutine);
|
||
}/*
|
||
BOOL Read(LPVOID AP_Buffer, DWORD AI_BufferSize, LPOVERLAPPED_COMPLETION_ROUTINE APF_CompletionRoutine)*/
|
||
|
||
DWORD Write(LPVOID AP_Buffer, DWORD AI_BufferSize)
|
||
{
|
||
DWORD VDW_WriteSize=0; ::WriteFile(
|
||
mh_Handle ,
|
||
AP_Buffer ,
|
||
AI_BufferSize ,
|
||
&VDW_WriteSize ,
|
||
this
|
||
/*/////////*/ ); //////////////////
|
||
|
||
return VDW_WriteSize;
|
||
}/*
|
||
DWORD Write(LPVOID AP_Buffer, DWORD AI_BufferSize)*/
|
||
|
||
BOOL Write(LPVOID AP_Buffer, DWORD AI_BufferSize, DWORD& ARR_WriteSize)
|
||
{
|
||
return ::WriteFile(mh_Handle,AP_Buffer, AI_BufferSize, &ARR_WriteSize,this);
|
||
}/*
|
||
BOOL Write(LPVOID AP_Buffer, DWORD AI_BufferSize, DWORD& ARR_WriteSize)*/
|
||
|
||
BOOL Write(LPVOID AP_Buffer, DWORD AI_BufferSize, LPOVERLAPPED_COMPLETION_ROUTINE APF_CompletionRoutine)
|
||
{
|
||
return ::WriteFileEx(mh_Handle, AP_Buffer, AI_BufferSize, this, APF_CompletionRoutine);
|
||
}/*
|
||
BOOL Write(LPVOID AP_Buffer, DWORD AI_BufferSize, LPOVERLAPPED_COMPLETION_ROUTINE APF_CompletionRoutine)*/
|
||
|
||
BOOL Cancel()
|
||
{
|
||
return ::CancelIo(mh_Handle);
|
||
}/*
|
||
BOOL Cancel()*/
|
||
|
||
BOOL GetFinishResult(DWORD& ARRI_FinishCode, BOOL AB_Wait=FALSE)
|
||
{
|
||
return ::GetOverlappedResult(mh_Handle, this, &ARRI_FinishCode, AB_Wait);
|
||
}/*
|
||
BOOL GetFinishResult(DWORD& ARRI_FinishCode, BOOL AB_Wait=FALSE)*/
|
||
|
||
DWORD GetFinishResult(BOOL AB_Wait=FALSE)
|
||
{
|
||
/*//////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ 이 object 로 비동기 입출력을 한 상태에서 현재 입출력 상태를 알기 위해
|
||
이 멤버를 호출하면 물론 안된다. 그때는
|
||
|
||
DWORD GetFinishResult(OVERLAPPED& ARR_OverLapped,BOOL AB_Wait=FALSE)
|
||
|
||
을 호출해야 한다. 즉 다른 OVERLAPPED object 로 입출력 상태를 통보받아야 한다.
|
||
|
||
//////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
DWORD VDW_FinishCode; ::GetOverlappedResult(
|
||
mh_Handle ,
|
||
this ,
|
||
&VDW_FinishCode ,
|
||
AB_Wait
|
||
/*//////////*/ ); //////////////////////////
|
||
|
||
return VDW_FinishCode;
|
||
}/*
|
||
DWORD GetFinishResult(BOOL AB_Wait=FALSE)*/
|
||
|
||
DWORD GetFinishResult(OVERLAPPED& ARR_OverLapped, BOOL AB_Wait=FALSE)
|
||
{
|
||
DWORD VDW_FinishCode; ::GetOverlappedResult(
|
||
mh_Handle ,
|
||
&ARR_OverLapped ,
|
||
&VDW_FinishCode ,
|
||
AB_Wait
|
||
/*/////////*/ ); ///////////////////////////
|
||
|
||
return VDW_FinishCode;
|
||
}/*
|
||
DWORD GetFinishResult(OVERLAPPED& ARR_OverLapped, BOOL AB_Wait=FALSE)*/
|
||
|
||
public:
|
||
};/*
|
||
class ZCAsynIO : public OVERLAPPED*/
|
||
|
||
|
||
/*////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ IOCP 지원정보
|
||
|
||
Client : Requires Windows Vista, Windows XP, or Windows 2000 Professional.
|
||
Server : Requires Windows Server 2008, Windows Server 2003, or Windows 2000 Server.
|
||
Header : Declared in WinBase.h; include Windows.h.
|
||
|
||
Library Use Kernel32.lib.
|
||
|
||
DLL Requires Kernel32.dll.
|
||
|
||
※ window95, window98 에서는 지원되지 않는다.
|
||
|
||
■ 관련함수
|
||
|
||
HANDLE CreateIoCompletionPort
|
||
(
|
||
HANDLE FileHandle ,
|
||
HANDLE ExistingCompletionPort ,
|
||
ULONG_PTR CompletionKey ,
|
||
DWORD NumberOfConcurrentThreads
|
||
);
|
||
|
||
□ 인수
|
||
|
||
※ FileHandle
|
||
|
||
[in] Handle to a file opened for overlapped I/O completion.
|
||
You must specify the FILE_FLAG_OVERLAPPED flag
|
||
when using the CreateFile function to obtain the handle.
|
||
If FileHandle specifies INVALID_HANDLE_VALUE,
|
||
CreateIoCompletionPort creates an I/O completion port
|
||
without associating it with a file. In this case,
|
||
the ExistingCompletionPort parameter must be NULL and the CompletionKey parameter is ignored.
|
||
|
||
※ ExistingCompletionPort
|
||
|
||
[in] Handle to the I/O completion port.
|
||
If this parameter specifies an existing completion port,
|
||
the function associates it with the file specified by the FileHandle parameter.
|
||
The function returns the handle of the existing completion port;
|
||
it does not create a new I/O completion port.
|
||
|
||
If this parameter is NULL,
|
||
the function creates a new I/O completion port and associates it with the file specified by FileHandle.
|
||
The function returns the handle to the new I/O completion port.
|
||
|
||
-- 이 인수가 NULL 이면 새로운 완료 포트를 만든다.
|
||
|
||
※ CompletionKey
|
||
|
||
[in] Per-file completion key that is included in every I/O completion packet for the specified file.
|
||
|
||
※ NumberOfConcurrentThreads
|
||
|
||
[in] Maximum number of threads that the operating system can allow
|
||
to concurrently process I/O completion packets for the I/O completion port.
|
||
This parameter is ignored if the ExistingCompletionPort parameter is not NULL.
|
||
If this parameter is zero, the system allows as many concurrently running threads
|
||
as there are processors in the system.
|
||
|
||
□ Return Values
|
||
|
||
If the function succeeds,
|
||
the return value is the handle to the I/O completion port
|
||
that is associated with the specified file.
|
||
|
||
If the function fails, the return value is NULL.
|
||
To get extended error information, call GetLastError.
|
||
|
||
|
||
BOOL GetQueuedCompletionStatus
|
||
(
|
||
HANDLE CompletionPort ,
|
||
LPDWORD lpNumberOfBytes ,
|
||
PULONG_PTR lpCompletionKey ,
|
||
LPOVERLAPPED* lpOverlapped ,
|
||
DWORD dwMilliseconds
|
||
);
|
||
|
||
□ Return Value
|
||
|
||
If the function dequeues a completion packet for a successful I/O operation
|
||
from the completion port, the return value is nonzero.
|
||
The function stores information in the variables pointed to
|
||
by the lpNumberOfBytes, lpCompletionKey, and lpOverlapped parameters.
|
||
|
||
If *lpOverlapped is NULL and the function does not dequeue a completion packet
|
||
from the completion port, the return value is zero.
|
||
The function does not store information in the variables pointed to
|
||
by the lpNumberOfBytes and lpCompletionKey parameters.
|
||
To get extended error information, call GetLastError.
|
||
If the function did not dequeue a completion packet because the wait timed out,
|
||
GetLastError returns WAIT_TIMEOUT.
|
||
|
||
-- *lpOverlapped 가 NULL 이고 즉 OVERLAPPED* 형 인수가 NULL 로 설정되고 완료 포트로부터 완료패
|
||
-- 킷을 가져오지 않는다면 반환값은 zero 이다. 이때 lpNumberOfBytes 와 lpCompletionKey 인수에
|
||
-- 값이 설정되지 않는다. 상세한 에러 정보는 GetLastError() 를 호출할 것. 이 함수가 타임아웃으로
|
||
-- 인해 완료패킷을 가져오지 않았다면 GetLastError() 은 WAIT_TIMEOUT 을 반환한다.
|
||
|
||
If *lpOverlapped is not NULL and the function dequeues a completion packet
|
||
for a failed I/O operation from the completion port, the return value is zero.
|
||
The function stores information in the variables pointed to
|
||
by lpNumberOfBytes, lpCompletionKey, and lpOverlapped.
|
||
To get extended error information, call GetLastError
|
||
|
||
-- *lpOverlapped 가 NULL 이 아니고 즉 OVERLAPPED* 형 인수가 NULL 이 아닌 값으로 설정되고 완료 포
|
||
-- 트로부터 완료패킷을 가져왔다면 반환값은 zero 이다. 이때 lpNumberOfBytes, lpCompletionKey,
|
||
-- lpOverlapped 인수에 유효한 값이 설정된다.
|
||
|
||
|
||
BOOL PostQueuedCompletionStatus(
|
||
HANDLE CompletionPort,
|
||
DWORD dwNumberOfBytesTransferred, // can be 0
|
||
ULONG_PTR dwCompletionKey,
|
||
LPOVERLAPPED lpOverlapped // can be null
|
||
);
|
||
|
||
typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
|
||
|
||
The PostQueuedCompletionStatus function posts an I/O completion packet to an I/O completion port.
|
||
|
||
-- 완료된 입출력 정보를 IOCP Queue 에 직접 전달하기 위해 사용하는 API. 이 함수를 호출하면
|
||
-- GetQueuedCompletionStatus 함수에서 받게 된다. IOCP가 반드시 파일이나, 네트웍의 전송으로만 사용
|
||
-- 되어야 할 필요는 없다. 스레드간의 통신에서도 CompletionKey 값을 주고받는 것으로 대체할 수도 있
|
||
-- 다
|
||
|
||
□ Parameters
|
||
|
||
CompletionPort
|
||
[in] Handle to an I/O completion port to which the I/O completion packet is to be posted.
|
||
dwNumberOfBytesTransferred
|
||
[in] Value to be returned through the lpNumberOfBytesTransferred parameter
|
||
of the GetQueuedCompletionStatus function.
|
||
dwCompletionKey
|
||
[in] Value to be returned through the lpCompletionKey parameter
|
||
of the GetQueuedCompletionStatus function.
|
||
lpOverlapped
|
||
[in] Value to be returned through the lpOverlapped parameter
|
||
of the GetQueuedCompletionStatus function.
|
||
|
||
※ dwNumberOfBytesTransferred can be 0
|
||
※ lpOverlapped can be null
|
||
|
||
□ Return Value
|
||
|
||
If the function succeeds, the return value is nonzero.
|
||
If the function fails, the return value is zero.
|
||
To get extended error information, call GetLastError.
|
||
|
||
□ Remarks
|
||
|
||
The I/O completion packet will satisfy an outstanding call
|
||
to the GetQueuedCompletionStatus function.
|
||
This function returns with the three values passed as the second, third, and fourth parameters
|
||
of the call to PostQueuedCompletionStatus.
|
||
The system does not use or validate these values.
|
||
In particular, the lpOverlapped parameter need not point to an OVERLAPPED structure.
|
||
|
||
■ --
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
class CWinIOCP
|
||
{
|
||
protected:
|
||
HANDLE mh_IOCP;
|
||
public :
|
||
|
||
CWinIOCP()
|
||
{
|
||
mh_IOCP=0;
|
||
}/*
|
||
CWinIOCP()*/
|
||
|
||
~CWinIOCP(){Close();}
|
||
|
||
bool Create(DWORD AI_ThreadCnt=0)
|
||
{
|
||
return (mh_IOCP=::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, AI_ThreadCnt))!=NULL;
|
||
}/*
|
||
bool Create(DWORD AI_ThreadCnt=0)*/
|
||
|
||
bool AddHandle(HANDLE AH_FileHandle, ULONG_PTR APL_Key, DWORD AI_ThreadCnt=0)
|
||
{
|
||
return ::CreateIoCompletionPort(AH_FileHandle, mh_IOCP, APL_Key, AI_ThreadCnt)!=NULL;
|
||
}/*
|
||
bool AddHandle(HANDLE AH_FileHandle,ULONG_PTR APL_Key, DWORD AI_ThreadCnt=0)*/
|
||
|
||
bool GetStatus(LPDWORD APL_NumberOfBytes, PULONG_PTR APL_CompletionKey, LPOVERLAPPED* APP_Overlapped, DWORD AI_Milliseconds=INFINITE)
|
||
{
|
||
return ::GetQueuedCompletionStatus(mh_IOCP, APL_NumberOfBytes, APL_CompletionKey, APP_Overlapped, AI_Milliseconds)==TRUE;
|
||
}/*
|
||
bool GetStatus(LPDWORD APL_NumberOfBytes, PULONG_PTR APL_CompletionKey, LPOVERLAPPED* APP_Overlapped, DWORD AI_Milliseconds=INFINITE)*/
|
||
|
||
bool GetStatus(LPDWORD APL_NumberOfBytes, PULONG_PTR APL_CompletionKey, LPOVERLAPPED& APRR_Overlapped, DWORD AI_Milliseconds=INFINITE)
|
||
{
|
||
return ::GetQueuedCompletionStatus(mh_IOCP, APL_NumberOfBytes, APL_CompletionKey, &APRR_Overlapped, AI_Milliseconds)==TRUE;
|
||
}/*
|
||
bool GetStatus(LPDWORD APL_NumberOfBytes, PULONG_PTR APL_CompletionKey, LPOVERLAPPED& APRR_Overlapped, DWORD AI_Milliseconds=INFINITE)*/
|
||
|
||
#if defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__>=200800
|
||
|
||
bool GetStatusEx(OVERLAPPED_ENTRY* AP_OvlpEntry, ULONG AI_EntryCnt, ULONG& ALRR_FetchEntry, DWORD AI_Milliseconds=INFINITE, BOOL AB_Alertable=TRUE)
|
||
{
|
||
return ::GetQueuedCompletionStatusEx(mh_IOCP, AP_OvlpEntry, AI_EntryCnt, &ALRR_FetchEntry, AI_Milliseconds, AB_Alertable)==TRUE;
|
||
}/*
|
||
bool GetStatusEx(OVERLAPPED_ENTRY* AP_OvlpEntry, ULONG AI_EntryCnt, ULONG& ALRR_FetchEntry, DWORD AI_Milliseconds=INFINITE, BOOL AB_Alertable=TRUE)*/
|
||
|
||
#endif //defined(__VISUAL_CPP_VER__) && __VISUAL_CPP_VER__>=200800
|
||
|
||
bool PostStatus(DWORD ADW_NumberOfBytes, ULONG_PTR APL_CompletionKey, LPOVERLAPPED AP_Overlapped=NULL)
|
||
{
|
||
return ::PostQueuedCompletionStatus(mh_IOCP, ADW_NumberOfBytes, APL_CompletionKey, AP_Overlapped)==TRUE;
|
||
}/*
|
||
bool PostStatus(DWORD ADW_NumberOfBytes, ULONG_PTR APL_CompletionKey, LPOVERLAPPED AP_Overlapped=NULL)*/
|
||
|
||
bool Close()
|
||
{
|
||
if(mh_IOCP==0) return true;
|
||
|
||
bool VB_IsOK =
|
||
::CloseHandle(mh_IOCP)==TRUE ;
|
||
|
||
mh_IOCP=0; return VB_IsOK;
|
||
}/*
|
||
bool Close()*/
|
||
|
||
HANDLE GetHandle()
|
||
{
|
||
return mh_IOCP;
|
||
}/*
|
||
HANDLE GetHandle()*/
|
||
|
||
public:
|
||
};/*
|
||
class CWinIOCP*/
|
||
|
||
|
||
#endif //defined(_WIN)
|
||
|
||
|
||
#ifndef _WIN
|
||
|
||
|
||
/*////////////////////////////////////////////////////////
|
||
|
||
■ RLIMIT_CPU // 초 단위의 CPU 시간
|
||
RLIMIT_FSIZE // 최대 파일 크기
|
||
RLIMIT_DATA // 최대 데이타 크기
|
||
RLIMIT_STACK // 최대 스택 크기
|
||
RLIMIT_CORE // 최대 코어 파일 크기
|
||
RLIMIT_RSS // 최대 거주 집합 크기
|
||
RLIMIT_NPROC // 최대 프로세스 수
|
||
RLIMIT_NOFILE // 최대 열 수 있는 파일의 수
|
||
RLIMIT_MEMLOCK // 최대 잠긴 기억 장소 주소 공간
|
||
RLIMIT_AS // 주소 공간(가상 메모리) 제한값
|
||
|
||
만일 RLIM_INFINITY 로 설정되었다면 자원은 무제한이다.
|
||
RLIMIT_OFILE는 RLIMIT_NOFILE에대한 BSD 이름이다.
|
||
|
||
■ rlimit 구조체는 다음과 같다:
|
||
|
||
struct rlimit
|
||
{
|
||
rlim_t rlim_cur;
|
||
rlim_t rlim_max;
|
||
};
|
||
|
||
■ -- 2010-02-10 22:43:00
|
||
|
||
■ http://carenam.egloos.com/9515070
|
||
|
||
ulimit -c 해서 core file size가 0 으로 되어 있다면 core file 이 생성되지 않음(linux 최초 기본값).
|
||
|
||
Core file size 변경 방법입니다.
|
||
|
||
방법1: ulimit -c unlimited <-- 한시적인 적용 (rebooting 후 해제 됨)
|
||
방법2: /etc/profile 파일 변경 <-- rebooting 후에도 설정 유지 됨
|
||
|
||
# No core files by default
|
||
ulimit -S -c 0 > /dev/null 2>&1 부분을 아래와 같이 수정
|
||
ulimit -S -c unlimited > /dev/null 2>&1
|
||
# source /etc/profile <-- /etc/profile을 수정 하였으므로 설정 값 적용.
|
||
|
||
/etc/security/limits.conf 파일 변경
|
||
* soft core -1 추가
|
||
* hard core -1 추가 ( -1은 무한 의미 )
|
||
|
||
ulimit -a 또는 ulimit -c 로 확인 <-- core file 생성 적용 여부 확인 (unlimited 또는 설정파일 크기)
|
||
|
||
-- 2010-05-19 23:12:00
|
||
|
||
////////////////////////////////////////////////////////*/
|
||
|
||
template<typename TLimitSize=rlim_t> class CResrcLimit_T : public rlimit
|
||
{
|
||
public:
|
||
|
||
TLimitSize GetCurSize() const
|
||
{
|
||
return this->rlim_cur;
|
||
}/*
|
||
TLimitSize GetCurSize() const*/
|
||
|
||
TLimitSize GetMaxSize() const
|
||
{
|
||
return this->rlim_max;
|
||
}/*
|
||
TLimitSize GetMaxSize() const*/
|
||
|
||
void SetCurSize(TLimitSize AI_LimitSize)
|
||
{
|
||
this->rlim_cur=AI_LimitSize;
|
||
}/*
|
||
void SetCurSize(TLimitSize AI_LimitSize)*/
|
||
|
||
void SetMaxSize(TLimitSize AI_LimitSize)
|
||
{
|
||
this->rlim_max=AI_LimitSize;
|
||
}/*
|
||
void SetMaxSize(TLimitSize AI_LimitSize)*/
|
||
|
||
void SetSize(TLimitSize AI_CurSize, TLimitSize AI_MaxSize)
|
||
{
|
||
this->rlim_cur=AI_CurSize;
|
||
this->rlim_max=AI_MaxSize;
|
||
}/*
|
||
void SetSize(TLimitSize AI_CurSize, TLimitSize AI_MaxSize)*/
|
||
|
||
bool GetInfo(int AI_Resource)
|
||
{
|
||
return ::getrlimit(AI_Resource, this)==0;
|
||
}/*
|
||
bool GetInfo(int AI_Resource)*/
|
||
|
||
void SetInfo(int AI_Resource)
|
||
{
|
||
return ::setrlimit(AI_Resource, this)==0;
|
||
}/*
|
||
void SetInfo(int AI_Resource)*/
|
||
|
||
public:
|
||
};/*
|
||
template<typename TLimitSize=rlim_t> class CResrcLimit_T : public rlimit */
|
||
|
||
|
||
/*///////////////////////////////////////
|
||
|
||
■ struct iovec
|
||
{
|
||
void* iov_base; // Starting address
|
||
size_t iov_len ; // Number of bytes
|
||
};
|
||
|
||
■ -- 2010-04-17 20:15:00
|
||
|
||
///////////////////////////////////////*/
|
||
|
||
|
||
template<int TVecSize=10> class ZtCIOBuffVec
|
||
{
|
||
public :
|
||
enum{EInvalidPos=-1 };
|
||
enum{EVecSize =TVecSize};
|
||
public :
|
||
typedef ::iovec StIOBuff;
|
||
protected:
|
||
::iovec mo_IOBuff[TVecSize];
|
||
ZTypLength mi_HeadPos ; // TVecSize 에서 유효한 처음 위치
|
||
ZTypLength mi_TailPos ; // TVecSize 에서 유효한 마지막 위치
|
||
ZTypLength ml_AllLen ; // 전체 버퍼 길이
|
||
public :
|
||
|
||
static char* GetCharsInVec ( StIOBuff& AR_StIOBuff){return (char*) AR_StIOBuff.iov_base;}
|
||
static const char* GetCharsInVec (const StIOBuff& AR_StIOBuff){return (const char*)AR_StIOBuff.iov_base;}
|
||
static size_t GetLengthInVec(const StIOBuff& AR_StIOBuff){return AR_StIOBuff.iov_len ;}
|
||
|
||
static void InitStIOBuff(StIOBuff& ARR_StIOBuff)
|
||
{
|
||
ARR_StIOBuff.iov_base=0;
|
||
ARR_StIOBuff.iov_len =0;
|
||
}/*
|
||
static void InitStIOBuff(StIOBuff& ARR_StIOBuff)*/
|
||
|
||
/*public:*/
|
||
public:
|
||
|
||
ZtCIOBuffVec()
|
||
{
|
||
Init();
|
||
}/*
|
||
ZtCIOBuffVec()*/
|
||
|
||
void Init()
|
||
{
|
||
mi_HeadPos=EInvalidPos;
|
||
mi_TailPos=EInvalidPos;
|
||
ml_AllLen =0 ;
|
||
}/*
|
||
void Init()*/
|
||
|
||
ZTypLength GetSize() const
|
||
{
|
||
return mi_HeadPos<=EInvalidPos ? 0 : (mi_TailPos-mi_HeadPos+1) ;
|
||
}/*
|
||
ZTypLength GetSize() const*/
|
||
|
||
ZTypLength GetAllLength() const
|
||
{
|
||
return ml_AllLen;
|
||
}/*
|
||
ZTypLength GetAllLength() const*/
|
||
|
||
bool IsFull() const
|
||
{
|
||
return GetSize()==EVecSize;
|
||
}/*
|
||
bool IsFull() const*/
|
||
|
||
StIOBuff& operator[](ZTypLength AI_Index)
|
||
{
|
||
return mo_IOBuff[AI_Index];
|
||
}/*
|
||
StIOBuff& operator[](ZTypLength AI_Index)*/
|
||
|
||
const StIOBuff& operator[](ZTypLength AI_Index) const
|
||
{
|
||
return mo_IOBuff[AI_Index];
|
||
}/*
|
||
const StIOBuff& operator[](ZTypLength AI_Index) const*/
|
||
|
||
bool IsEqual(ZTypLength AI_BuffIndex, char* APC_Buff, ZTypLength AI_Length)
|
||
{
|
||
// AI_BuffIndex 번 원소가 APC_Buff, AI_Length 인지 확인하는 함수.
|
||
// 주로 DEBUG 목적으로 설계한 함수이다.
|
||
|
||
if(AI_BuffIndex<0 || AI_BuffIndex>=EVecSize)
|
||
{ return false; }
|
||
|
||
return GetCharsInVec (mo_IOBuff[AI_BuffIndex])==APC_Buff &&
|
||
GetLengthInVec(mo_IOBuff[AI_BuffIndex])==AI_Length ;
|
||
//////
|
||
}/*
|
||
bool IsEqual(ZTypLength AI_BuffIndex, char* APC_Buff, ZTypLength AI_Length)*/
|
||
|
||
bool AddBuff(char* APC_Buff, ZTypLength AI_Length)
|
||
{
|
||
if(AI_Length<1 || mi_TailPos+1>=TVecSize)
|
||
{ return false; }
|
||
|
||
if(mi_HeadPos<=EInvalidPos)
|
||
{ mi_HeadPos=0; }
|
||
|
||
mo_IOBuff[++mi_TailPos].iov_base=APC_Buff ;
|
||
mo_IOBuff[ mi_TailPos].iov_len =AI_Length;
|
||
|
||
ml_AllLen+=AI_Length; return true;
|
||
}/*
|
||
bool AddBuff(char* APC_Buff, ZTypLength AI_Length)*/
|
||
|
||
template<typename TString> bool AddBuffCStr(TString& AR_CString)
|
||
{
|
||
return AddBuff(AR_CString.data(), AR_CString.size());
|
||
}/*
|
||
template<typename TString> bool AddBuffCStr(TString& AR_CString)*/
|
||
|
||
int MinusLength(ZTypLength AL_Length, ZTypLength* APL_LastInvalidByte=0)
|
||
{
|
||
/*//////////////////////////////////////////////////////////////////////
|
||
|
||
■ mo_WSABuff 의 유효버퍼에서 AL_Length 만큼 처리가 된 것으로 셋팅한다.
|
||
|
||
■ int VI_EmptyBuffCnt(처리 후 비어 있게 되는 버퍼 갯수)를 반환한다.
|
||
|
||
■ long* APL_LastInvalidByte 에 유효한 mo_IOBuff 중 마지막 원소에서 무효
|
||
화되는 바이트 길이를 전달한다.
|
||
|
||
//////////////////////////////////////////////////////////////////////*/
|
||
|
||
if(AL_Length<1 ) return 0 ;
|
||
if(ml_AllLen<AL_Length) AL_Length=ml_AllLen ;
|
||
|
||
// 이때 mi_HeadPos, mi_TailPos 에 유효한 값이 들어있다.
|
||
|
||
int VI_EmptyBuffCnt= 0 ;
|
||
::iovec* VP_IOBuff = mo_IOBuff+mi_HeadPos;
|
||
|
||
for(int i=mi_HeadPos; i<=mi_TailPos; ++i)
|
||
{
|
||
if(AL_Length>=ZNsMain::ZTypInt(VP_IOBuff->iov_len))
|
||
{
|
||
AL_Length -= VP_IOBuff->iov_len;
|
||
ml_AllLen -= VP_IOBuff->iov_len;
|
||
|
||
++VI_EmptyBuffCnt;
|
||
|
||
if(++mi_HeadPos>mi_TailPos)
|
||
{
|
||
Init(); return VI_EmptyBuffCnt;
|
||
}
|
||
if(AL_Length<=0)
|
||
{
|
||
return VI_EmptyBuffCnt;
|
||
}
|
||
}
|
||
else // AL_Length<ZNsMain::ZTypInt(VP_IOBuff->iov_len)
|
||
{
|
||
if(APL_LastInvalidByte!=0)
|
||
*APL_LastInvalidByte=AL_Length;
|
||
|
||
VP_IOBuff->iov_base = (char*)(VP_IOBuff->iov_base)+AL_Length;
|
||
VP_IOBuff->iov_len -= AL_Length;
|
||
ml_AllLen -= AL_Length;
|
||
|
||
return VI_EmptyBuffCnt;
|
||
}/*
|
||
else // AL_Length<ZNsMain::ZTypInt(VP_IOBuff->iov_len)*/
|
||
|
||
++VP_IOBuff;
|
||
}/*
|
||
for(int i=mi_HeadPos; i<=mi_TailPos; ++i)*/
|
||
|
||
return VI_EmptyBuffCnt;
|
||
}/*
|
||
int MinusLength(ZTypLength AL_Length, ZTypLength* APL_LastInvalidByte=0)*/
|
||
|
||
StIOBuff* GetHeadBuffPtr()
|
||
{
|
||
return mi_HeadPos<=EInvalidPos ? 0 : mo_IOBuff+mi_HeadPos ;
|
||
}/*
|
||
StIOBuff* GetHeadBuffPtr()*/
|
||
|
||
void MoveFirst()
|
||
{
|
||
if(mi_HeadPos<1) return ;
|
||
|
||
int VI_Index= 0, i = mi_HeadPos;
|
||
int VI_ValidBuffCnt = GetSize() ;
|
||
|
||
for(; i<=mi_TailPos; ++i)
|
||
{
|
||
mo_IOBuff[VI_Index++]=mo_IOBuff[i];
|
||
}/*
|
||
for(; i<=mi_TailPos; ++i)*/
|
||
|
||
// mi_HeadPos 개 만큼을 앞으로 이동시켰으므로
|
||
// 이 다음 유효하지 않은 mi_HeadPos 개 StIOBuff 버퍼를 초기화한다.
|
||
|
||
for(i=0; i<mi_HeadPos; ++i)
|
||
{
|
||
InitStIOBuff(RR(mo_IOBuff[VI_Index++]));
|
||
}/*
|
||
for(i=0; i<mi_HeadPos; ++i)*/
|
||
|
||
mi_HeadPos= 0 ; mi_TailPos= VI_ValidBuffCnt-1;
|
||
}/*
|
||
void MoveFirst()*/
|
||
|
||
template<typename TString> void SetInfoCStr(
|
||
TString& ARR_CStringInfo, const char* APC_Indent="")
|
||
{
|
||
// 이 함수는 주로 DEBUG 를 위해 설계하였다.
|
||
|
||
ARR_CStringInfo(APC_Indent)("All Buffer Cnt=")(EVecSize) ("\r\n");
|
||
ARR_CStringInfo(APC_Indent)("Use Buffer Cnt=")(GetSize()) ("\r\n");
|
||
ARR_CStringInfo(APC_Indent)("All Byte Cnt=")(GetAllLength())("\r\n");
|
||
ARR_CStringInfo(APC_Indent)("HeadPos=")(mi_HeadPos)(", TailPos=")(mi_TailPos)("\r\n");
|
||
|
||
if(mi_HeadPos<=EInvalidPos) return;
|
||
|
||
for(int i=mi_HeadPos; i<=mi_TailPos; ++i)
|
||
{
|
||
ARR_CStringInfo(APC_Indent)("i=")(i)(" : Length=")(GetLengthInVec(mo_IOBuff[i]))("\r\n");
|
||
ARR_CStringInfo(APC_Indent)(" Data=\"")(GetCharsInVec(mo_IOBuff[i]),GetLengthInVec(mo_IOBuff[i]))("\"\r\n");
|
||
}/*
|
||
for(int i=mi_HeadPos; i<=mi_TailPos; ++i)*/
|
||
}/*
|
||
template<typename TString> void SetInfoCStr(
|
||
TString& ARR_CStringInfo, const char* APC_Indent="") */
|
||
|
||
public:
|
||
};/*
|
||
template<int TVecSize=10> class ZtCIOBuffVec*/
|
||
|
||
|
||
template<> class ZtCIOBuffVec<0>
|
||
{
|
||
public:
|
||
enum{EInvalidPos=-1};
|
||
enum{EVecSize = 0};
|
||
public:
|
||
typedef ::iovec StIOBuff;
|
||
public:
|
||
|
||
ZtCIOBuffVec(){}
|
||
|
||
void Init(){}
|
||
|
||
int GetSize() const {return 0;}
|
||
|
||
bool AddBuff(
|
||
char* APC_Buff, ZTypLength AI_Length){return false;}
|
||
|
||
void MinusLength(long AL_Length){}
|
||
|
||
StIOBuff* GetHeadBuffPtr(){return 0;}
|
||
|
||
void MoveFirst(){}
|
||
|
||
public:
|
||
};/*
|
||
template<> class ZtCIOBuffVec<0>*/
|
||
|
||
|
||
#endif //!_WIN
|
||
|
||
|
||
|
||
/*#######################################################################################################
|
||
|
||
■ 아래 WriteFileRaw() 함수는 원래, ZtCStringBase<> 의 멤버 함수로 WriteFile() 라는 정적 멤버 함수였으나
|
||
이미 같은 이름의 비정적 멤버 함수가 있다 보니, 두 개 함수를 사용했을 때, g++ 4.4.7 에서 경고가 발생했
|
||
었다.
|
||
|
||
[sauron@localhost Donut_CPP]$ g++ -g -D_DEBUG -D_REENTRANT DonutTopCheck.cpp -o DonutTopCheck_D.exe -lpthread -I../../../my_CPP/CPP_Std/ -I../../../my_CPP/CPP_Net/ -I../../../my_CPP/CPP_Main/
|
||
DonutTopCheck.cpp: In static member function 'static void std::CSngtChecker::Exec()::HandleLine::Exec(CStringData&)':
|
||
DonutTopCheck.cpp:235: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
|
||
Donut.H:23376: note: candidate 1: static bool std::ZtCStringBase<TTypCh, TAlloc, TAllocSize, TTypeString>::WriteFile(const TTypCh*, const typename TTypeString::ZCTypeChars::TypeChar*, typename TTypeString::ZCTypeChars::TypeLength, bool, int) [with TTypCh = char, TAlloc = std::ZtCAllocClass<char>, TAllocSize = std::ZtCAllocMemSize<char>, TTypeString = std::ZNsType::ZtCTypeStringBase<char, std::ZtCAllocClass<char>, std::ZtCAllocMemSize<char>, long int>]
|
||
Donut.H:23318: note: candidate 2: bool std::ZtCStringBase<TTypCh, TAlloc, TAllocSize, TTypeString>::WriteFile(const TTypCh*, bool, int) const [with TTypCh = char, TAlloc = std::ZtCAllocClass<char>, TAllocSize = std::ZtCAllocMemSize<char>, TTypeString = std::ZNsType::ZtCTypeStringBase<char, std::ZtCAllocClass<char>, std::ZtCAllocMemSize<char>, long int>]
|
||
DonutTopCheck.cpp:235: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
|
||
Donut.H:23376: note: candidate 1: static bool std::ZtCStringBase<TTypCh, TAlloc, TAllocSize, TTypeString>::WriteFile(const TTypCh*, const typename TTypeString::ZCTypeChars::TypeChar*, typename TTypeString::ZCTypeChars::TypeLength, bool, int) [with TTypCh = char, TAlloc = std::ZtCAllocClass<char>, TAllocSize = std::ZtCAllocMemSize<char>, TTypeString = std::ZNsType::ZtCTypeStringBase<char, std::ZtCAllocClass<char>, std::ZtCAllocMemSize<char>, long int>]
|
||
Donut.H:23318: note: candidate 2: bool std::ZtCStringBase<TTypCh, TAlloc, TAllocSize, TTypeString>::WriteFile(const TTypCh*, bool, int) const [with TTypCh = char, TAlloc = std::ZtCAllocClass<char>, TAllocSize = std::ZtCAllocMemSize<char>, TTypeString = std::ZNsType::ZtCTypeStringBase<char, std::ZtCAllocClass<char>, std::ZtCAllocMemSize<char>, long int>]
|
||
|
||
그래서 WriteFileRaw() 로 이름을 바꾸고, std 의 전역 함수로 뺀 것이다. -- 2015-09-25 20:15:00
|
||
|
||
■ ZfWriteFileRaw() 로 이름을 바꾸었다. -- 2025-08-11 10:52
|
||
|
||
#######################################################################################################*/
|
||
|
||
static bool ZfWriteFileRaw /*//////////////////////////////////////////////////////////////////////////*/
|
||
(
|
||
ZTypCPCh APC_FileName , ZTypCPCh APC_Content ,
|
||
ZTypLength AL_ContentLen, bool AB_DoAppend=true, int AI_RightMode=-1
|
||
)
|
||
/*#####################################################################################################*/
|
||
{
|
||
// int AI_RightMode = -1 은 리눅스에서만 쓴다.
|
||
|
||
#ifdef _WIN
|
||
|
||
HANDLE VH_File = ::CreateFileA(
|
||
APC_FileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
|
||
|
||
if(VH_File==INVALID_HANDLE_VALUE) return false;
|
||
|
||
if(AB_DoAppend==true)
|
||
::SetFilePointer(VH_File, 0, NULL, FILE_END); // 덧붙이는 경우라면 파일 포인터를 맨 끝으로 옮긴다.
|
||
else ::SetEndOfFile (VH_File ); // 덧붙이는 경우가 아니면 기존 내용을 지운다.
|
||
|
||
DWORD NumberOfBytesWritten = 0 ;
|
||
|
||
if(::WriteFile(VH_File, APC_Content, AL_ContentLen, &NumberOfBytesWritten, NULL)==FALSE)
|
||
{
|
||
::CloseHandle(VH_File); return false;
|
||
}/*
|
||
if(::WriteFile(VH_File, APC_Content, AL_ContentLen, &NumberOfBytesWritten, NULL)==FALSE)*/
|
||
|
||
return ::CloseHandle(VH_File)==TRUE ;
|
||
|
||
|
||
#else // !defined(_WIN)
|
||
|
||
// 리눅스의 경우
|
||
|
||
using ZNsConst::ZNsLlioMode::AppendMake ;
|
||
using ZNsConst::ZNsLlioMode::WriteMakeCut;
|
||
|
||
ZTycInt CI_FileOpenErr = -1 ;
|
||
ZTycInt CI_FileOpenTag =
|
||
(
|
||
AI_RightMode<0 ?
|
||
S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP :
|
||
AI_RightMode
|
||
) ;
|
||
//////////////////////////////////
|
||
|
||
int AH_FileDesc = CI_FileOpenErr ;
|
||
|
||
if(AB_DoAppend==true)
|
||
{
|
||
const bool CB_IsError = ////////////////////////////////////
|
||
(
|
||
(
|
||
AH_FileDesc = ::open
|
||
( APC_FileName, AppendMake, CI_FileOpenTag )
|
||
)==CI_FileOpenErr
|
||
);
|
||
////////////////////////////////////////////////////////////
|
||
|
||
if(CB_IsError) return false; ///////////////////////////////
|
||
}
|
||
else
|
||
{
|
||
const bool CB_IsError = ////////////////////////////////////
|
||
(
|
||
(
|
||
AH_FileDesc = ::open
|
||
( APC_FileName, WriteMakeCut, CI_FileOpenTag )
|
||
)==CI_FileOpenErr
|
||
);
|
||
//////////////////////////////////////////////////////////////
|
||
|
||
if(CB_IsError) return false; /////////////////////////////////
|
||
}/*
|
||
else*/
|
||
|
||
if(::write(AH_FileDesc, APC_Content, AL_ContentLen)<AL_ContentLen)
|
||
{
|
||
::close(AH_FileDesc); return false;
|
||
}/*
|
||
if(::write(AH_FileDesc, APC_Content, AL_ContentLen)<AL_ContentLen)*/
|
||
|
||
return ::close(AH_FileDesc)==0 ;
|
||
|
||
#endif //!defined(_WIN)
|
||
}/*
|
||
static bool ZfWriteFileRaw( /////////////////////////////////////////////////////////////////////////////
|
||
(
|
||
ZTypCPCh APC_FileName , ZTypCPCh APC_Content ,
|
||
ZTypLength AL_ContentLen, bool AB_DoAppend=true, int AI_RightMode=-1
|
||
)
|
||
#######################################################################################################*/
|
||
|
||
|
||
template<typename TStringData> bool ZftLoadFile /*////////////////////////////*/
|
||
(
|
||
TStringData& ARR_SaveCStr , ZTypCPCChar APC_FileName ,
|
||
ZTypLength AL_LoadSize=0 , ZTypLength AL_Offset =0,
|
||
bool AB_DoAppend=true
|
||
)
|
||
/*#############################################################################*/
|
||
{
|
||
// window 에서 _open() 함수는 \r\n 을 한 문자로 입력받음에 주의.
|
||
|
||
if(AL_Offset<0) AL_Offset=0;
|
||
|
||
typedef ZtCCharType<TStringData> ZCCharType;
|
||
typedef typename ZCCharType::TypeChar Typechar ;
|
||
|
||
#ifndef _WIN
|
||
|
||
int AH_FileDesc = ::open
|
||
(APC_FileName, ZNsConst::ZNsLlioMode::Read);
|
||
|
||
if(AH_FileDesc == -1) return false;
|
||
|
||
// 파일 기술자를 파일의 맨 끝으로 이동시켜 파일 크기를 구한다.
|
||
|
||
off_t VL_LastPos = ::lseek
|
||
(AH_FileDesc, 0/*Offset*/, SEEK_END); // 실패시 -1
|
||
|
||
if(VL_LastPos == -1 || VL_LastPos<=AL_Offset)
|
||
{ ::close(AH_FileDesc); return false; }
|
||
/*******************************************/
|
||
|
||
VL_LastPos -= AL_Offset;
|
||
|
||
if(AL_LoadSize>0 && VL_LastPos>AL_LoadSize)
|
||
{ VL_LastPos=AL_LoadSize; }
|
||
/*=======================================*/
|
||
|
||
::lseek(AH_FileDesc, AL_Offset, SEEK_SET);
|
||
|
||
ZTypLength VL_PrevSize =
|
||
(AB_DoAppend ? ARR_SaveCStr.size() : 0);
|
||
|
||
ARR_SaveCStr.resize //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
(
|
||
VL_PrevSize+VL_LastPos-AL_Offset, ' '
|
||
);
|
||
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||
|
||
// 윈도우에서 read() 함수는 \r\n 을 한 문자로 읽어들이므로 주의
|
||
|
||
ZTypLength VL_ReadSize = 0 ;
|
||
ZTypCPChar VP_CopyStart =
|
||
const_cast<ZTypPChar>(ARR_SaveCStr.data())+VL_PrevSize ;
|
||
|
||
if((VL_ReadSize = ::read(AH_FileDesc, VP_CopyStart, VL_LastPos))<0)
|
||
{
|
||
ARR_SaveCStr.resize(VL_PrevSize, Typechar(0));
|
||
|
||
::close(AH_FileDesc); return true; /*********/
|
||
}
|
||
/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
|
||
|
||
ARR_SaveCStr.resize(VL_PrevSize+VL_ReadSize, Typechar(0));
|
||
|
||
::close(AH_FileDesc); return true; /*********************/
|
||
|
||
#else //defined(_WIN)
|
||
|
||
ZTypLength VL_PrevSize = (AB_DoAppend ? ARR_SaveCStr.size() : 0) ;
|
||
HANDLE VH_File = ::CreateFileA /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
|
||
(
|
||
APC_FileName ,
|
||
GENERIC_READ ,
|
||
FILE_SHARE_READ , // 공유모드: 이미 열려 있는 파일을 열 수 있게 한다.
|
||
NULL ,
|
||
OPEN_EXISTING ,
|
||
FILE_ATTRIBUTE_NORMAL, // 반드시 단독으로 사용되는 플래그
|
||
NULL
|
||
);
|
||
/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
|
||
|
||
if(INVALID_HANDLE_VALUE==VH_File) return false;
|
||
|
||
DWORD dwRead2 = 0 ;
|
||
DWORD dwRead =
|
||
::SetFilePointer(VH_File, 0, NULL, FILE_END);
|
||
|
||
dwRead -= AL_Offset;
|
||
|
||
if(AL_LoadSize>0 && dwRead>AL_LoadSize)
|
||
{ dwRead=AL_LoadSize; }
|
||
|
||
ARR_SaveCStr.resize //>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||
(
|
||
VL_PrevSize + dwRead, ' '
|
||
);
|
||
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||
|
||
::SetFilePointer(VH_File, AL_Offset, NULL, FILE_BEGIN);
|
||
|
||
ZTypCPChar VP_CopyStart =
|
||
const_cast<ZTypPChar>(ARR_SaveCStr.data())+VL_PrevSize ;
|
||
|
||
if(::ReadFile(VH_File, (LPVOID)VP_CopyStart, dwRead, &dwRead2, NULL)==FALSE)
|
||
{
|
||
ARR_SaveCStr.resize(VL_PrevSize+dwRead2, Typechar(0));
|
||
|
||
::CloseHandle(VH_File); return false; /**************/
|
||
}
|
||
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
|
||
|
||
::CloseHandle(VH_File);
|
||
|
||
if(dwRead2>0)
|
||
ARR_SaveCStr.resize(VL_PrevSize+dwRead2, Typechar(0));
|
||
else ARR_SaveCStr.resize(VL_PrevSize , Typechar(0));
|
||
|
||
return true;
|
||
|
||
#endif //defined(_WIN)
|
||
}/*
|
||
template<typename TStringData> bool ZftLoadFile ////////////////////////////////
|
||
(
|
||
TStringData& ARR_SaveCStr , ZTypCPCChar APC_FileName ,
|
||
ZTypLength AL_LoadSize=0 , ZTypLength AL_Offset =0,
|
||
bool AB_DoAppend=true
|
||
)
|
||
###############################################################################*/
|
||
|
||
|
||
}/*
|
||
namespace ZNsMain*/
|
||
|
||
|
||
/*///////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
■ ZCDir 클래스에서 사용된 readdir() 함수를 _REENTRANT 매크로가 정의되어 있는 경우,
|
||
readdir_r() 을 사용하는 것으로 바꾸었다. man 페이지에서는 readdir_r() 대신에
|
||
getdents() 을 사용할 것을 권고하고 있으나, freebsd 에서는 인수가 약간 다르고,
|
||
실제 테스트에 자꾸 core dump 가 발생하여 readdir_r() 을 사용하는 것으로 하였다.
|
||
|
||
int getdents(unsigned int fd, struct dirent* dirp, unsigned int count ); // In Linux
|
||
int getdents(int fd , char *buf , int nbytes); // In FreeBSD
|
||
int getdents(int fildes , struct dirent *buf , size_t nbyte ); // In solaris
|
||
|
||
OS 별로 선언이 다른 것이 지저분해 보인다.
|
||
|
||
-- 2012-05-07 01:19:00
|
||
|
||
그리고 getdents() 보다 readdir_r() 을 사용한 것이 결국 좋았다. AIX(115.21.49.210)에서
|
||
확인 결과, getdents() 는 없어도 readdir_r() 은 있었다. 즉 readdir_r() 이 좀 더 많은 OS
|
||
에서 지원된다고 봐도 된다. (2012-05-07 01:27:00)
|
||
|
||
///////////////////////////////////////////////////////////////////////////////////////*/
|
||
|
||
|
||
#endif //__ZCPPMAIIN__MAINHEAD_EX_H__
|