first commit

This commit is contained in:
hyzboy 2019-08-23 10:54:57 +08:00
parent 9790a5757c
commit f768bbec4b
65 changed files with 5551 additions and 0 deletions

8
CMakeLists.txt Normal file
View File

@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.0)
project(CMPlatform)
include(path_config.cmake)
CMPlatformSetup(${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(${CMPLATFORM_ROOT_SOURCE_PATH})

View File

@ -0,0 +1,207 @@
#ifndef HGL_INPUT_DEVICE_INCLUDE
#define HGL_INPUT_DEVICE_INCLUDE
namespace hgl
{
/**
*
*/
enum MouseButton
{
mbMove =0x00000001, ///<鼠标移动了
mbLeft =0x00000002, ///<鼠标左键处于按下状态
mbMid =0x00000004, ///<鼠标中键处于按下状态
mbRight =0x00000008, ///<鼠标右键处于按下状态
mbX1 =0x00000010,
mbX2 =0x00000020,
mbShift =0x10000000, ///<Shift键处于按下状态
mbCtrl =0x20000000, ///<Ctrl键处于按下状态
};
/**
*
*/
enum KeyboardButton
{
kbBeginRange=0,
//主键盘区
kbEsc, ///<ESC
//F功能键
kbF1, ///<F1
kbF2, ///<F2
kbF3, ///<F3
kbF4, ///<F4
kbF5, ///<F5
kbF6, ///<F6
kbF7, ///<F7
kbF8, ///<F8
kbF9, ///<F9
kbF10, ///<F10
kbF11, ///<F11
kbF12, ///<F12
kbGrave, //<`号(主键盘数字键1左边的按钮)
//10个数字
kb0, ///<数字键0
kb1, ///<数字键1
kb2, ///<数字键2
kb3, ///<数字键3
kb4, ///<数字键4
kb5, ///<数字键5
kb6, ///<数字键6
kb7, ///<数字键7
kb8, ///<数字键8
kb9, ///<数字键9
kbMinus, ///< - (减号)
kbEquals, ///< = (等号)
kbBackSlash, ///< \ (反斜杠)
kbBackSpace, ///< 退格键
kbTab, ///<Tab键
kbA, ///<A
kbB, ///<B
kbC, ///<C
kbD, ///<D
kbE, ///<E
kbF, ///<F
kbG, ///<G
kbH, ///<H
kbI, ///<I
kbJ, ///<J
kbK, ///<K
kbL, ///<L
kbM, ///<M
kbN, ///<N
kbO, ///<O
kbP, ///<P
kbQ, ///<Q
kbR, ///<R
kbS, ///<S
kbT, ///<T
kbU, ///<U
kbV, ///<V
kbW, ///<W
kbX, ///<X
kbY, ///<Y
kbZ, ///<Z
kbLeftBracket, ///<[
kbRightBracket, ///<]
kbCapsLock, ///<大写锁定键
kbSemicolon, ///<; (分号)
kbApostrophe, ///<' (单引号)
kbEnter, ///<回车键
kbLeftShift, ///<左边的Shift键
kbComma, ///<, (逗号)
kbPeriod, ///<. (句号)
kbSlash, ///</ (除号)
kbRightShift, ///<右边的Shift键
kbLeftCtrl, ///<左边的Ctrl键
kbLeftOS, ///<左边的OS键(Win/Apple键)
kbLeftAlt, ///<左边的Alt键
kbSpace, ///<空格键
kbRightAlt, ///<右边的Alt键
kbRightOS, ///<右边的OS键(Win/Apple键)
kbRightMenu, ///<右边的Menu键
kbRightCtrl, ///<右边的Ctrl键
//中键盘区
kbPrintScreen, ///<打印屏幕键
kbScrollLock, ///<滚动锁定键
kbPause, ///<暂停键
kbInsert, ///<插入键
kbDelete, ///<删除键
kbHome, ///<行首键
kbEnd, ///<行尾键
kbPageUp, ///<向前翻页键
kbPageDown, ///<向后翻页键
kbUp, ///<↑光标键
kbDown, ///<↓光标键
kbLeft, ///<←光标键
kbRight, ///<→光标键
//小键盘区
kbNumLock, ///<小键盘 数字锁定键
kbNumAdd, ///<小键盘 +
kbNumSubtract, ///<小键盘 -
kbNumMultiply, ///<小键盘 *
kbNumDivide, ///<小键盘 /
kbNum0, ///<小键盘 0
kbNum1, ///<小键盘 1
kbNum2, ///<小键盘 2
kbNum3, ///<小键盘 3
kbNum4, ///<小键盘 4
kbNum5, ///<小键盘 5
kbNum6, ///<小键盘 6
kbNum7, ///<小键盘 7
kbNum8, ///<小键盘 8
kbNum9, ///<小键盘 9
kbNumDecimal, ///<小键盘 . (小数点/删除键)
kbNumEnter, ///<小键盘 回车键
kbEndRange,
kbRangeSize=kbEndRange-kbBeginRange+1
};//enum KeyboardButton
/**
*
*/
enum JoystickButton
{
jbBeginRange=0,
jbUp,
jbDown,
jbLeft,
jbRight,
jb0, jb1, jb2, jb3, jb4, jb5, jb6, jb7,
jb8, jb9, jb10, jb11, jb12, jb13, jb14, jb15,
jb16, jb17, jb18, jb19, jb20, jb21, jb22, jb23,
jb24, jb25, jb26, jb27, jb28, jb29, jb30, jb31,
jbEnd,
//DreamCast/XBOX
/* jbX=jb2,
jbY=jb3,
jbA=jb0,
jbB=jb1,
jbL=jb4,
jbR=jb5,*/
//PlayStation
jbTriangle =jb0, // 三角
jbCircle =jb1, // 圆
jbFork =jb2, // 叉
jbRectangle =jb3, // 方
jbL1 =jb6, jbL2 =jb4,
jbR1 =jb7, jbR2 =jb5,
jbSelect =jb8, jbStart =jb9,
//XBOX/XBOX360
jbXBOX, //西瓜键
jbEndRange,
jbRangeSize=jbEndRange-jbBeginRange+1
};
}//namespace hgl
#endif//HGL_INPUT_DEVICE_INCLUDE

12
inc/hgl/platform/Vulkan.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef HGL_PLATFORM_VULKAN_INCLUDE
#define HGL_PLATFORM_VULKAN_INCLUDE
#include<vulkan/vulkan.h>
namespace hgl
{
class Window;
VkSurfaceKHR CreateVulkanSurface(VkInstance,Window *);
}//namespace hgl
#endif//HGL_PLATFORM_VULKAN_INCLUDE

119
inc/hgl/platform/Window.h Normal file
View File

@ -0,0 +1,119 @@
#ifndef HGL_GRAPH_WINDOW_INCLUDE
#define HGL_GRAPH_WINDOW_INCLUDE
#include<hgl/type/BaseString.h>
#include<hgl/platform/InputDevice.h>
namespace hgl
{
class Window
{
protected:
uint width,height;
bool full_screen;
OSString win_name;
bool active;
bool is_close;
bool is_min;
bool key_push[kbRangeSize];
protected:
virtual bool MessageProc()=0;
virtual bool WaitMessage()=0;
public:
virtual void ProcMouseMove (int x,int y) {SafeCallEvent(OnMouseMove, (x,y));}
virtual void ProcMouseWheel (int v,int h,uint mb) {SafeCallEvent(OnMouseWheel, (v,h,mb));}
virtual void ProcMouseDown (int x,int y,uint mb) {SafeCallEvent(OnMouseDown, (x,y,mb));}
virtual void ProcMouseUp (int x,int y,uint mb) {SafeCallEvent(OnMouseUp, (x,y,mb));}
virtual void ProcMouseDblClick (int x,int y,uint mb) {SafeCallEvent(OnMouseDblClick, (x,y,mb));}
//virtual void ProcJoystickDown (uint);
//virtual void ProcJoystickPress (uint);
//virtual void ProcJoystickUp (uint);
virtual void ProcKeyDown (KeyboardButton);
virtual void ProcKeyPress (KeyboardButton kb){SafeCallEvent(OnKeyPress,(kb));}
virtual void ProcKeyUp (KeyboardButton);
virtual void ProcChar (os_char ch){SafeCallEvent(OnChar,(ch));}
virtual void ProcResize (uint,uint);
virtual void ProcActive (bool);
virtual void ProcClose ();
public:
uint GetWidth()const{return width;}
uint GetHeight()const{return height;}
public:
DefEvent(void,OnMouseMove ,(int,int));
DefEvent(void,OnMouseWheel ,(int,int,uint));
DefEvent(void,OnMouseDown ,(int,int,uint));
DefEvent(void,OnMouseUp ,(int,int,uint));
DefEvent(void,OnMouseDblClick ,(int,int,uint));
//DefEvent(void,OnJoystickDown ,(uint));
//DefEvent(void,OnJoystickPress ,(uint));
//DefEvent(void,OnJoystickUp ,(uint));
DefEvent(void,OnKeyDown ,(KeyboardButton));
DefEvent(void,OnKeyPress,(KeyboardButton));
DefEvent(void,OnKeyUp ,(KeyboardButton));
DefEvent(void,OnChar ,(os_char));
DefEvent(void,OnResize ,(uint,uint));
DefEvent(void,OnActive ,(bool));
DefEvent(void,OnClose ,());
public:
Window(const OSString &wn)
{
width=height=0;
full_screen=false;
win_name=wn;
active=false;
is_close=true;
is_min=false;
hgl_zero(key_push);
}
virtual ~Window()=default;
virtual bool Create(uint,uint)=0;
virtual bool Create(uint,uint,uint)=0;
virtual void Close()=0;
bool IsMin()const{return is_min;}
bool IsClose()const{return is_close;}
bool IsVisible()const{return (!is_close)&&width&&height;}
virtual void SetCaption(const OSString &)=0;
virtual void Show()=0;
virtual void Hide()=0;
virtual void ToMinWindow()=0;
virtual void ToMaxWindow()=0;
virtual void SetSystemCursor(bool){}
virtual bool Update();
};//class Window
Window *CreateRenderWindow(const OSString &win_name);
void InitNativeWindowSystem();
}//namespace hgl
#endif//HGL_GRAPH_WINDOW_INCLUDE

9
path_config.cmake Normal file
View File

@ -0,0 +1,9 @@
macro(CMPlatformSetup source_path)
message("CMPLATFORM_ROOT_PATH: " ${source_path})
set(CMPLATFORM_ROOT_INCLUDE_PATH ${source_path}/inc)
set(CMPLATFORM_ROOT_SOURCE_PATH ${source_path}/src)
include_directories(${CMPLATFORM_ROOT_INCLUDE_PATH})
endmacro()

344
src/Android/AndroidMain.cpp Normal file
View File

@ -0,0 +1,344 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "AndroidProject1.NativeActivity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "AndroidProject1.NativeActivity", __VA_ARGS__))
/**
* Our saved state data.
*/
struct saved_state
{
float angle;
int32_t x;
int32_t y;
};
/**
* Shared state for our app.
*/
struct engine
{
struct android_app* app;
ASensorManager* sensorManager;
const ASensor* accelerometerSensor;
ASensorEventQueue* sensorEventQueue;
ASensorEvent acceleration_event;
int animating;
EGLDisplay display;
EGLSurface surface;
EGLContext context;
int32_t width;
int32_t height;
struct saved_state state;
};
/**
* Initialize an EGL context for the current display.
*/
static int engine_init_display(struct engine* engine)
{
// initialize OpenGL ES and EGL
/*
* Here specify the attributes of the desired configuration.
* Below, we select an EGLConfig with at least 8 bits per color
* component compatible with on-screen windows
*/
const EGLint config_attrs[] =
{
EGL_DEPTH_SIZE, 0,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_STENCIL_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //即使是用es3这里也写es2
EGL_NONE
};
const EGLint context_attrs[] =
{
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
EGLint w, h, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
EGLint config_count;
bool depth_check=false;
const EGLint depth_bit_sizes[]={24,16};
for(uint i=0;i<sizeof(depth_bit_sizes)/sizeof(EGLint);i++)
{
config_attrs[1]=depth_bit_sizes[i];
if(eglChooseConfig(display,config_attrs,&egl_config,1,&config_count)==EGL_TRUE)
if(config_count>0)
{
depth_check=true;
break;
}
}
if(!depth_check)
return(-1);
/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
* As soon as we picked a EGLConfig, we can safely reconfigure the
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
surface = eglCreateWindowSurface(display, config, engine->app->window, nullptr);
context = eglCreateContext(display, config, nullptr, context_attrs);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
{
LOGW("Unable to eglMakeCurrent");
return -1;
}
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
engine->display = display;
engine->context = context;
engine->surface = surface;
engine->width = w;
engine->height = h;
engine->state.angle = 0;
// Initialize GL state.
Cube_setupGL(w, h);
return 0;
}
/**
* Just the current frame in the display.
*/
static void engine_draw_frame(struct engine* engine)
{
if (engine->display == nullptr) {
// No display.
return;
}
Cube_prepare();
Cube_draw();
eglSwapBuffers(engine->display, engine->surface);
}
/**
* Tear down the EGL context currently associated with the display.
*/
static void engine_term_display(struct engine* engine)
{
if (engine->display != EGL_NO_DISPLAY)
{
eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (engine->context != EGL_NO_CONTEXT)
{
eglDestroyContext(engine->display, engine->context);
}
if (engine->surface != EGL_NO_SURFACE)
{
eglDestroySurface(engine->display, engine->surface);
}
eglTerminate(engine->display);
}
engine->animating = 0;
engine->display = EGL_NO_DISPLAY;
engine->context = EGL_NO_CONTEXT;
engine->surface = EGL_NO_SURFACE;
Cube_tearDownGL();
}
/**
* Process the next input event.
*/
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
{
struct engine* engine = (struct engine*)app->userData;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
{
engine->state.x = AMotionEvent_getX(event, 0);
engine->state.y = AMotionEvent_getY(event, 0);
return 1;
}
return 0;
}
/**
* Process the next main command.
*/
static void engine_handle_cmd(struct android_app* app, int32_t cmd)
{
struct engine* engine = (struct engine*)app->userData;
switch (cmd)
{
case APP_CMD_SAVE_STATE: // The system has asked us to save our current state. Do so.
engine->app->savedState = malloc(sizeof(struct saved_state));
*((struct saved_state*)engine->app->savedState) = engine->state;
engine->app->savedStateSize = sizeof(struct saved_state);
break;
case APP_CMD_INIT_WINDOW: // The window is being shown, get it ready.
if (engine->app->window != nullptr)
{
engine_init_display(engine);
engine_draw_frame(engine);
}
break;
case APP_CMD_TERM_WINDOW: // The window is being hidden or closed, clean it up.
engine_term_display(engine);
break;
case APP_CMD_GAINED_FOCUS: // When our app gains focus, we start monitoring the accelerometer.
if (engine->accelerometerSensor != nullptr)
{
ASensorEventQueue_enableSensor(engine->sensorEventQueue,engine->accelerometerSensor);
// We'd like to get 60 events per second (in us).
ASensorEventQueue_setEventRate(engine->sensorEventQueue,engine->accelerometerSensor, (1000L / 60) * 1000);
}
break;
case APP_CMD_LOST_FOCUS: // When our app loses focus, we stop monitoring the accelerometer.
// This is to avoid consuming battery while not being used.
if (engine->accelerometerSensor != nullptr)
{
ASensorEventQueue_disableSensor(engine->sensorEventQueue,engine->accelerometerSensor);
}
// Also stop animating.
engine->animating = 0;
engine_draw_frame(engine);
break;
}
}
/**
* This is the main entry point of a native application that is using
* android_native_app_glue. It runs in its own thread, with its own
* event loop for receiving input events and doing other things.
*/
void android_main(struct android_app* state)
{
struct engine engine;
memset(&engine, 0, sizeof(engine));
state->userData = &engine;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
engine.app = state;
// Prepare to monitor accelerometer
engine.sensorManager = ASensorManager_getInstance();
engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager,ASENSOR_TYPE_ACCELEROMETER);
engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager,state->looper, LOOPER_ID_USER, nullptr, nullptr);
if (state->savedState != nullptr)
{
// We are starting with a previous saved state; restore from it.
engine.state = *(struct saved_state*)state->savedState;
}
engine.animating = 1;
// loop waiting for stuff to do.
while (1)
{
// Read all pending events.
int ident;
int events;
struct android_poll_source* source;
// If not animating, we will block forever waiting for events.
// If animating, we loop until all events are read, then continue
// to draw the next frame of animation.
while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, nullptr, &events,(void**)&source)) >= 0)
{
// Process this event.
if (source != nullptr)
{
source->process(state, source);
}
// If a sensor has data, process it now.
if (ident == LOOPER_ID_USER)
{
if (engine.accelerometerSensor != nullptr)
{
while (ASensorEventQueue_getEvents(engine.sensorEventQueue,&engine->acceleration_event;, 1) > 0)
{
LOGI("accelerometer: x=%f y=%f z=%f",
engine->acceleration_event.acceleration.x,
engine->acceleration_event.acceleration.y,
engine->acceleration_event.acceleration.z);
}
}
}
// Check if we are exiting.
if (state->destroyRequested != 0)
{
engine_term_display(&engine);
return;
}
}
if (engine.animating)
{
// Done with events; draw next animation frame.
Cube_update();
//if (engine.state.angle > 1) {
// engine.state.angle = 0;
//}
// Drawing is throttled to the screen update rate, so there
// is no need to do timing here.
engine_draw_frame(&engine);
}
}
}

View File

@ -0,0 +1,29 @@
#include"AndroidWindow.h"
#include<vulkan/vulkan_android.h>
namespace hgl
{
VkSurfaceKHR AndroidWindow::CreateSurface(VkInstance vk_inst)
{
PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
GET_INSTANCE_PROC_ADDR(vk_inst,CreateAndroidSurfaceKHR);
if(!CreateAndroidSurfaceKHR)
return(nullptr);
VkAndroidSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
createInfo.window = AndroidGetApplicationWindow();
VkSurfaceKHR surface;
VkResult res=CreateAndroidSurfaceKHR(vk_inst,&createInfo,nullptr,&surface);
if(res!=VK_SUCCESS)
return(nullptr);
return(surface);
}
}//namespace hgl

109
src/Android/AssetManage.cpp Normal file
View File

@ -0,0 +1,109 @@
#include<hgl/filesystem/AssetManage.h>
#include<hgl/io/InputStream.h>
#include<android/asset_manager.h>
#include<android/asset_manager_jni.h>
namespace hgl
{
namespace
{
static AAssetManager *asset_manager=nullptr;
class AndroidAssetInputStream:public io::InputStream
{
AAsset *asset;
public:
AndroidAssetInputStream(AAsset *a)
{
asset=a;
}
~AndroidAssetInputStream()
{
Close();
}
void Close() override
{
if(!asset)return;
AAsset_close(asset);
asset=nullptr;
}
int64 Read(void *data,int64 size) override
{
return AAsset_read(asset,data,size);
}
int64 Peek(void *data,int64 size) override
{
int64 left=Avaiable();
if(left<size)
size=left;
int64 result=Read(data,size);
if(result>0)
Seek(-result,SeekOrigin::Current);
return result;
}
int64 ReadFully(void *buf,int64 buf_size){return Read(buf,buf_size);} ///<充分读取,保证读取到指定长度的数据(不计算超时)
bool CanRestart()const override{return(true);}
bool CanSeek()const override{return(true);}
bool CanSize()const override{return(true);}
bool CanPeek()const override{return(false);}
bool Restart() override
{
Seek(0,soBegin);
return(true);
}
int64 Skip(int64 size) override
{
return Seek(size,SeekOrigin::Current);
}
int64 Seek(int64 offset,SeekOrigin so) override
{
return AAsset_seek64(asset,offset,(int)so);
}
int64 Tell()const override
{
return Seek(0,SeekOrigin::Current);
}
int64 GetSize()const override
{
return AAsset_getLength64(asset);
}
int64 Available()const override
{
return AAsset_getRemainingLength64(asset);
}
};//class AndroidAssetInputStream:public io::InputStream
}//namespace
void InitAssetManager(AAssetManager *am)
{
asset_manager=am;
}
io::InputStream *OpenAsset(const UTF8String &filename)
{
AAsset *asset = AAssetManager_open(asset_manager, filename.c_str(), AASSET_MODE_BUFFER);
if(!asset)return(nullptr);
return(new AndroidAssetInputStream(asset));
}
}//namespace hgl

View File

@ -0,0 +1,25 @@
#include<hgl/platform/Platform.h>
#include<jni.h>
namespace hgl
{
namespace logger
{
void SetLocalAppdataPath(const char *fn);
}//namespace logger
void InitAndroidSupport(JNIEnv *env,jobject obj)
{
jclass cls =env->GetObjectClass(obj);
jmethodID getFilesDir =env->GetMethodID(cls, "getFilesDir", "()Ljava/io/File;");
jobject dirobj =env->CallObjectMethod(obj,getFilesDir);
jclass dir =env->GetObjectClass(dirobj);
jmethodID getStoragePath =env->GetMethodID(dir, "getAbsolutePath", "()Ljava/lang/String;");
jstring path =(jstring)env->CallObjectMethod(dirobj, getStoragePath);
const char *pathstr =env->GetStringUTFChars(path, 0);
logger::SetLocalAppdataPath(pathstr);
env->ReleaseStringUTFChars(path, pathstr);
}
}//namespace hgl

146
src/Android/LogConsole.cpp Normal file
View File

@ -0,0 +1,146 @@
#include<hgl/Logger.h>
#include<hgl/CodePage.h>
#include<hgl/thread/ThreadMutex.h>
#include<unistd.h>
#include<pthread.h>
#ifdef LOG_INFO_TIME
#include<hgl/Time.h>
#endif//LOG_INFO_TIME
#include<android/log.h>
namespace hgl
{
namespace logger
{
constexpr uint LOG_BUF_SIZE=4096;
constexpr android_LogPriority android_priority[]={ ANDROID_LOG_ERROR, //llError
ANDROID_LOG_WARN, //llProblem
ANDROID_LOG_INFO, //llHint
ANDROID_LOG_VERBOSE}; //llLog
/**
* Android控制台日志插件接口
*/
class LogAndroidConsole:public Logger
{
char endline;
char thread_string[256];
char time_string[256];
char log_buf[LOG_BUF_SIZE];
#ifdef LOGINFO_THREAD_MUTEX
ThreadMutex mutex;
#endif//LOGINFO_THREAD_MUTEX
android_LogPriority prio;
public:
LogAndroidConsole(LogLevel ll):Logger(ll)
{
prio=android_priority[ll];
endline='\n';
}
bool Create(const OSString &)
{
return(true);
}
void Close(){}
#ifdef LOG_INFO_THREAD
void WriteThreadID()
{
memcpy(thread_string,"[Thread:",8);
htos(thread_string+8,128-9,pthread_self());
strcat(thread_string,LOG_BUF_SIZE,']');
}
#endif//LOG_INFO_THREAD
#ifdef LOG_INFO_TIME
void WriteTime()
{
memcpy(time_string,"[Time:",6);
ftos(time_string+6,128-strlen(time_string),GetDoubleTime());
strcat(time_string,LOG_BUF_SIZE,']');
}
#endif//LOG_INFO_TIME
void Write(const u16char *str,int size)
{
#ifdef LOGINFO_THREAD_MUTEX
mutex.Lock();
#endif//LOGINFO_THREAD_MUTEX
log_buf[0]=0;
#ifdef LOG_INFO_THREAD
WriteThreadID();
strcpy(log_buf,LOG_BUF_SIZE,thread_string);
#endif//LOG_INFO_THREAD
#ifdef LOG_INFO_TIME
WriteTime();
strcat(log_buf,LOG_BUF_SIZE,time_string);
#endif//LOG_INFO_TIME
int len;
len=u16_to_u8(log_buf+hgl::strlen(log_buf),LOG_BUF_SIZE,str,size);
if(len>0)
{
log_buf[len++]=0;
__android_log_write(prio,"",log_buf);
}
#ifdef LOGINFO_THREAD_MUTEX
mutex.Unlock();
#endif//LOGINFO_THREAD_MUTEX
}
void Write(const char *str,int size)
{
#ifdef LOGINFO_THREAD_MUTEX
mutex.Lock();
#endif//LOGINFO_THREAD_MUTEX
log_buf[0]=0;
#ifdef LOG_INFO_THREAD
WriteThreadID();
strcpy(log_buf,LOG_BUF_SIZE,thread_string);
#endif//LOG_INFO_THREAD
#ifdef LOG_INFO_TIME
WriteTime();
strcat(log_buf,LOG_BUF_SIZE,time_string);
#endif//LOG_INFO_TIME
strcpy(log_buf,LOG_BUF_SIZE,str,size);
__android_log_write(prio,"",log_buf);
#ifdef LOGINFO_THREAD_MUTEX
mutex.Unlock();
#endif//LOGINFO_THREAD_MUTEX
}
};//class LogAndroidConsole:public Logger
Logger *CreateLoggerConsole(const OSString &,LogLevel ll)
{
if(ll<llError)
return(nullptr);
return(new LogAndroidConsole(ll));
}
}//logger
}//namespace hgl

View File

@ -0,0 +1,15 @@
#include<hgl/platform/Platform.h>
#include<android/native_activity.h>
namespace hgl
{
namespace logger
{
void SetLocalAppdataPath(const char *fn);
}//namespace logger
void InitAndroidSupport(struct ANativeActivity *native_activity)
{
logger::SetLocalAppdataPath(native_activity->internalDataPath);
}
}//namespace hgl

View File

@ -0,0 +1,75 @@
#include<hgl/type/BaseString.h>
#include<unistd.h>
#include<pwd.h>
#include<unistd.h>
namespace hgl
{
namespace filesystem
{
namespace
{
char files_dir[HGL_MAX_PATH];
}
void SetLocalAppdataPath(const char *fn)
{
strcpy(files_dir,HGL_MAX_PATH,fn);
}
void GetLocalAppdataPath(char fn[HGL_MAX_PATH])
{
strcpy(fn,HGL_MAX_PATH,files_dir);
}
/**
*
*/
bool GetCurrentProgram(OSString &result)
{
os_char *path=new os_char[HGL_MAX_PATH];
const int len=readlink("/proc/self/exe",path,HGL_MAX_PATH);
if(len<=0)
{
delete[] path;
return(false);
}
path[len]=0;
result.Set(path,len,true);
return(true);
}
/**
*
*/
bool GetCurrentProgramPath(OSString &result)
{
os_char *path=new os_char[HGL_MAX_PATH];
const int len=readlink("/proc/self/exe",path,HGL_MAX_PATH);
if(len<=0)
{
delete[] path;
return(false);
}
os_char *right=hgl::strrchr(path,len,HGL_DIRECTORY_SEPARATOR);
if(right)
*right=0;
else
path[len]=0;
result.Set(path,len,true);
return(true);
}
}//namespace filesystem
}//namespace hgl

42
src/Apple/ProgramPath.mm Normal file
View File

@ -0,0 +1,42 @@
#include<hgl/type/BaseString.h>
#import <Foundation/Foundation.h>
namespace hgl
{
namespace filesystem
{
void GetLocalAppdataPath(char fn[HGL_MAX_PATH])
{
NSFileManager *dfm=[NSFileManager defaultManager];
const char *str=[[[dfm homeDirectoryForCurrentUser] path] cStringUsingEncoding:NSUTF8StringEncoding];
hgl::strcpy(fn,HGL_MAX_PATH,str,strlen(str));
}
/**
* 取得当前程序完整路径名称
*/
bool GetCurrentProgram(UTF8String &result)
{
NSString *ns_string = [[[[NSBundle mainBundle] bundleURL] URLByDeletingPathExtension] path];
result.Set([ns_string cStringUsingEncoding:NSUTF8StringEncoding]);
return(true);
}
/**
* 取得当前程序所在路径
*/
bool GetCurrentProgramPath(UTF8String &result)
{
NSString *ns_string = [[[[NSBundle mainBundle] bundleURL] URLByDeletingLastPathComponent] path];
result.Set([ns_string cStringUsingEncoding:NSUTF8StringEncoding]);
return(true);
}
}//namespace filesystem
}//namespace hgl

78
src/Apple/Semaphore.cpp Normal file
View File

@ -0,0 +1,78 @@
#include<hgl/thread/Semaphore.h>
#include<hgl/LogInfo.h>
#include<pthread.h>
#include<dispatch/dispatch.h>
namespace hgl
{
void GetWaitTime(struct timespec &,double);
/**
* @param max_count
*/
Semaphore::Semaphore(int max_count)
{
ptr=dispatch_semaphore_create(0);
if(!ptr)
{
LOG_ERROR(OS_TEXT("dispatch_semaphore_create error"));
ptr=nullptr;
}
}
Semaphore::~Semaphore()
{
if(!ptr)return;
dispatch_release(ptr);
}
/**
*
* @param n
* @return
*/
bool Semaphore::Post(int n)
{
if(!ptr)return(false);
if(n<=0)return(false);
for(int i=0;i<n;i++)
dispatch_semaphore_signal(ptr);
return(true);
}
/**
*
* @return
*/
bool Semaphore::TryAcquire()
{
if(!ptr)return(false);
return !dispatch_semaphore_wait(ptr, DISPATCH_TIME_NOW);
}
/**
*
* @param t ,使0.()
* @return ,,,false
*/
bool Semaphore::Acquire(double t)
{
if(!ptr)return(false);
if(t<=0)
{
return !dispatch_semaphore_wait(ptr, DISPATCH_TIME_FOREVER);
}
else
{
dispatch_time_t when=dispatch_time(DISPATCH_TIME_NOW,t*HGL_NANO_SEC_PER_SEC);
return !dispatch_semaphore_wait(ptr,when);
}
}
}//namespace hgl

132
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,132 @@
IF(UNIX)
SET(PLATFORM_FILE_SOURCE UNIX/File.cpp
UNIX/FileAccess.cpp
UNIX/EnumFile.cpp)
SET(PLATFORM_SYSTEM_INFO_SOURCE UNIX/SystemInfo.cpp)
SET(PLATFORM_MULTI_THREAD_SOURCE UNIX/CondVar.cpp
UNIX/RWLock.cpp
UNIX/Thread.cpp
UNIX/ThreadMutex.cpp)
IF(ANDROID)
SET(PLATFORM_LOG_SOURCE Android/LogConsole.cpp)
SET(PLATFORM_APPLICATION_SOURCE ${PLATFORM_APPLICATION_SOURCE}
Android/JNISupport.cpp
Android/NativeActivitySupport.cpp)
SET(PLATFORM_FILE_SOURCE ${PLATFORM_FILE_SOURCE}
Android/ProgramPath.cpp
Android/AssetManage.cpp)
SET(PLATFORM_MULTI_THREAD_SOURCE ${PLATFORM_MULTI_THREAD_SOURCE}
UNIX/Semaphore.cpp)
SET(PLATFORM_WINDOW_SOURCE Android/AndroidVulkan.cpp)
ELSE()
SET(PLATFORM_CODEPAGE_SOURCE UNIX/CodePage.cpp)
SET(PLATFORM_LOG_SOURCE UNIX/LogConsole.cpp)
IF(APPLE)
SET(PLATFORM_MULTI_THREAD_SOURCE ${PLATFORM_MULTI_THREAD_SOURCE}
Apple/Semaphore.cpp)
SET(PLATFORM_FILE_SOURCE ${PLATFORM_FILE_SOURCE}
Apple/ProgramPath.mm)
ELSE()
SET(PLATFORM_MULTI_THREAD_SOURCE ${PLATFORM_MULTI_THREAD_SOURCE}
UNIX/Semaphore.cpp)
SET(PLATFORM_FILE_SOURCE ${PLATFORM_FILE_SOURCE}
UNIX/ProgramPath.cpp)
SET(PLATFORM_WINDOW_SOURCE UNIX/XCBWindow.cpp
UNIX/XCBVulkan.cpp)
ENDIF()
ENDIF()
SET(PLATFORM_MULTI_PROCESS_SOURCE UNIX/ProcMutex.cpp
UNIX/Process.cpp
UNIX/Pipe.cpp
UNIX/Fifo.cpp)
SET(PLATFORM_TIME_SOURCE UNIX/Time.cpp
UNIX/Exit.cpp
UNIX/DateTime.cpp)
SET(PLATFORM_EXTERNAL_MODULE_SOURCE UNIX/ExternalModule.cpp)
ENDIF()
IF(WIN32)
SET(PLATFORM_FILE_SOURCE Win/File.cpp
Win/FileAccess.cpp
Win/EnumFile.cpp
Win/EnumVolume.cpp
Win/ProgramPath.cpp)
SET(PLATFORM_CODEPAGE_SOURCE Win/CodePage.cpp)
SET(PLATFORM_SYSTEM_INFO_SOURCE Win/SystemInfo.cpp)
SET(PLATFORM_LOG_SOURCE Win/LogConsole.cpp
Win/LogDialog.cpp)
SET(PLATFORM_MULTI_THREAD_SOURCE
Win/CondVar.cpp
Win/RWLock.cpp
Win/Semaphore.cpp
Win/Thread.cpp
Win/ThreadMutex.cpp)
SET(PLATFORM_MULTI_PROCESS_SOURCE Win/ProcMutex.cpp
Win/Pipe.cpp
Win/Fifo.cpp)
SET(PLATFORM_TIME_SOURCE Win/Time.cpp
Win/DateTime.cpp)
SET(PLATFORM_EXTERNAL_MODULE_SOURCE Win/ExternalModule.cpp)
SET(PLATFORM_DESKTOP_SOURCE Win/Desktop.cpp)
SET(PLATFORM_WINDOW_SOURCE Win/WinWindow.h
Win/WinWindow.cpp
Win/WinMessage.cpp
Win/WinVulkan.cpp)
ENDIF(WIN32)
SET(PLATFORM_WINDOW_SOURCE ${PLATFORM_WINDOW_SOURCE} Window.cpp)
SOURCE_GROUP("InputDevice" FILES ${PLATFORM_INPUT_DEVICE_SOURCE})
SOURCE_GROUP("CodePage" FILES ${PLATFORM_CODEPAGE_SOURCE})
SOURCE_GROUP("File" FILES ${PLATFORM_FILE_SOURCE})
SOURCE_GROUP("SystemInfo" FILES ${PLATFORM_SYSTEM_INFO_SOURCE})
SOURCE_GROUP("Application" FILES ${PLATFORM_APPLICATION_SOURCE})
SOURCE_GROUP("LogInfo" FILES ${PLATFORM_LOG_SOURCE})
SOURCE_GROUP("MultiThread" FILES ${PLATFORM_MULTI_THREAD_SOURCE})
SOURCE_GROUP("MultiProcess" FILES ${PLATFORM_MULTI_PROCESS_SOURCE})
SOURCE_GROUP("Time" FILES ${PLATFORM_TIME_SOURCE})
SOURCE_GROUP("Desktop" FILES ${PLATFORM_DESKTOP_SOURCE})
SOURCE_GROUP("Window" FILES ${PLATFORM_WINDOW_SOURCE})
SET(PLATFORM_SOURCE ${PLATFORM_SOURCE}
${PLATFORM_FILE_SOURCE}
${PLATFORM_CODEPAGE_SOURCE}
#${PLATFORM_SYSTEM_INFO_SOURCE}
${PLATFORM_APPLICATION_SOURCE}
${PLATFORM_LOG_SOURCE}
${PLATFORM_MULTI_THREAD_SOURCE}
${PLATFORM_MULTI_PROCESS_SOURCE}
${PLATFORM_TIME_SOURCE}
${PLATFORM_EXTERNAL_MODULE_SOURCE}
${PLATFORM_INPUT_DEVICE_SOURCE}
${PLATFORM_WINDOW_SOURCE}
)
add_library(CMPlatform STATIC ${PLATFORM_SOURCE})
set_property(TARGET CMPlatform PROPERTY FOLDER "CM")

125
src/UNIX/CodePage.cpp Normal file
View File

@ -0,0 +1,125 @@
#include<hgl/CodePage.h>
/**
* linux iconv
* by hyz in Friday,March 30,2012
*
* iconv(icont_t *cd,
* char **inbuf,size_t *inbytesleft,
* char **outbuf,size_t *outbytesleft);
*
* ps: 1.outbuf中inbuf,outbuf一定要备份一份出来用
* 2.inbytesleft中得到的是剩下还没有转完的总字节数
* 3.outbytesleft中得到的是剩下还没有用完的输出区总字节数
*/
#include<iconv.h>
#include<errno.h>
namespace hgl
{
template<typename T,typename S>
int CharSetConv(T **out_buf,const CharSetName &out_charset,
const S *in_str,int in_str_size,const CharSetName &in_charset)
{
if(!out_buf||!out_charset||!*out_charset
||!in_str||!*in_str||in_str_size==0||!in_charset||!*in_charset)
return(-1);
iconv_t cd=iconv_open(out_charset,in_charset);
if(cd==(iconv_t)-1)
return(-1);
if(in_str_size<0)
in_str_size=strlen(in_str);
size_t result;
char *in;
char *out;
T *out_str;
T *out_new;
size_t in_left;
size_t out_left;
int out_malloc_size=in_str_size;
int last_left=-1;
out_str=new T[out_malloc_size+1];
in=(char *)in_str;
out=(char *)out_str;
in_left=in_str_size;
out_left=out_malloc_size*sizeof(T);
while(true)
{
size_t res=iconv(cd,&in,&in_left,&out,&out_left);
if(res==(size_t)(-1))
{
if(errno==E2BIG)
{
out_new=new T[out_malloc_size*2];
if(!out_new)
return(false);
result=out-(char *)out_str;
memcpy(out_new,out_str,result);
out_malloc_size*=2;
delete[] out_str;
out_str=out_new;
out=(char *)out_str;
out+=result;
//in_left已经被减了所以不用处理
out_left=(out_malloc_size*sizeof(T))-result;
continue;
}
else if(errno==EILSEQ) //有非法字符,跳过
{
in++;
in_left--;
continue;
}
}
break;
}
//result=(out_malloc_size-(out_left/sizeof(T));
result=((T *)out)-out_str; // 同上一行
out_str[result]=0;
iconv_close(cd);
*out_buf=out_str;
return(result);
}
int to_utf16(const CharSet &cs,u16char **dst,const char *src,const int src_size)
{
return CharSetConv<u16char,char>(dst,endian::GetCharSet<u16char>(),src,src_size,cs.charset);
}
int utf16_to(const CharSet &cs,char **dst,const u16char *src,const int src_size)
{
return CharSetConv<char,u16char>(dst,cs.charset,src,src_size,endian::GetCharSet<u16char>());
}
int to_utf8(const CharSet &cs,char **dst,const char *src,const int src_size)
{
return CharSetConv<char,char>(dst,utf8_charset,src,src_size,cs.charset);
}
int utf8_to(const CharSet &cs,char **dst,const char *src,const int src_size)
{
return CharSetConv<char,char>(dst,cs.charset,src,src_size,utf8_charset);
}
}//namespace hgl

47
src/UNIX/CondVar.cpp Normal file
View File

@ -0,0 +1,47 @@
#include<hgl/thread/CondVar.h>
#include<hgl/thread/ThreadMutex.h>
#include<pthread.h>
namespace hgl
{
void GetWaitTime(struct timespec &,double);
CondVar::CondVar()
{
cond_var=new pthread_cond_t;
pthread_cond_init((pthread_cond_t *)cond_var,nullptr);
}
CondVar::~CondVar()
{
pthread_cond_destroy((pthread_cond_t *)cond_var);
delete (pthread_cond_t *)cond_var;
}
bool CondVar::Wait(ThreadMutex *tm,double t)
{
if(t>0)
{
struct timespec abstime;
GetWaitTime(abstime,t);
return(!pthread_cond_timedwait((pthread_cond_t *)cond_var,tm->GetThreadMutex(),&abstime));
}
else
{
return(!pthread_cond_wait((pthread_cond_t *)cond_var,tm->GetThreadMutex()));
}
}
void CondVar::Signal()
{
pthread_cond_signal((pthread_cond_t *)cond_var);
}
void CondVar::Broadcast()
{
pthread_cond_broadcast((pthread_cond_t *)cond_var);
}
}//namespace hgl

125
src/UNIX/DateTime.cpp Normal file
View File

@ -0,0 +1,125 @@
#include<hgl/type/DataType.h>
#include<hgl/type/DateTime.h>
#include<hgl/io/DataInputStream.h>
#include<hgl/io/DataOutputStream.h>
#include<hgl/thread/RWLock.h>
#include<time.h>
#include<sys/time.h>
namespace hgl
{
//和系统时间同步
void Time::Sync(const double cur_time)
{
tm m;
time_t tt;
if(cur_time<=0)
{
struct timeval tv;
gettimeofday(&tv, nullptr);
tt=tv.tv_sec;
micro_seconds=tv.tv_usec;
}
else
{
tt=cur_time;
micro_seconds=(cur_time-tt)*HGL_MICRO_SEC_PER_SEC;
}
localtime_r(&tt,&m);
hours =m.tm_hour;
minutes =m.tm_min;
seconds =m.tm_sec;
week_day =m.tm_wday;
gmt_off =m.tm_gmtoff;
}
}//namespace hgl
//--------------------------------------------------------------------------------------------------
namespace hgl
{
void Date::Sync(const double cur_time)
{
tm m;
time_t tt;
if(cur_time<=0)
{
struct timeval tv;
gettimeofday(&tv, nullptr);
tt=tv.tv_sec;
}
else
{
tt=cur_time;
}
localtime_r(&tt,&m);
year =m.tm_year+1900;
SetMonth(m.tm_mon+1);
SetDay (m.tm_mday);
week_day=m.tm_wday;
year_day=m.tm_yday;
}
}//namespace hgl
namespace hgl
{
void ToDateTime(Date &d,Time &t,const double cur_time)
{
tm m;
time_t tt;
uint micro_sec;
if(cur_time<=0)
{
struct timeval tv;
gettimeofday(&tv, nullptr);
tt=tv.tv_sec;
micro_sec=tv.tv_usec;
}
else
{
tt=cur_time;
micro_sec=(cur_time-tt)*HGL_MICRO_SEC_PER_SEC;
}
localtime_r(&tt,&m);
d.Set(m.tm_year+1900,m.tm_mon+1,m.tm_mday,m.tm_wday,m.tm_yday);
t.Set(m.tm_hour,m.tm_min,m.tm_sec,micro_sec,m.tm_wday);
t.SetGMT(m.tm_gmtoff);
}
double FromDateTime(const int year,const int month,const int day,
const int hour,const int minute,const int second,const int micro_second,
const int gmt_off)
{
tm at;
hgl_zero(at);
at.tm_year =year-1900;
at.tm_mon =month-1;
at.tm_mday =day;
at.tm_hour =hour;
at.tm_min =minute;
at.tm_sec =second;
at.tm_gmtoff=gmt_off;
double result=mktime(&at);
return(result + (double(micro_second) / HGL_MICRO_SEC_PER_SEC));
}
}//namespace hgl

141
src/UNIX/EnumFile.cpp Normal file
View File

@ -0,0 +1,141 @@
#include<hgl/filesystem/EnumFile.h>
#include<hgl/LogInfo.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>
#include<dirent.h>
#include<sys/types.h>
#include<sys/stat.h>
namespace hgl
{
namespace filesystem
{
/**
*
* @param config
* @return ,<0
*/
int EnumFile::Enum(EnumFileConfig *config)
{
if(!config)RETURN_ERROR(-1);
if(config->folder_name.IsEmpty())RETURN_ERROR(-4);
OSString fullname;
int count=0;
if(config->folder_name.IsEmpty())
{
fullname='.';
}
else
{
fullname=config->folder_name;
}
DIR *dir;
struct_dirent64 *entry;
struct_stat64 statbuf;
FileInfo fi;
char path_buf[HGL_MAX_PATH]={0};
getcwd(path_buf,HGL_MAX_PATH);
chdir(fullname);
if((dir = opendir(fullname)) == NULL)
return(-1);
if((entry = hgl_readdir64(dir)) == NULL)
return(-1);
int sub_count;
do
{
if(strcmp(entry->d_name,".")==0
||strcmp(entry->d_name,"..")==0)
{
continue;
}
memset(&statbuf,0,sizeof(struct_stat64));
if(hgl_lstat64(entry->d_name,&statbuf)==-1)
continue;
if(S_ISDIR(statbuf.st_mode))
{
if(!config->proc_folder)continue;
}
else
{
if(!config->proc_file)continue;
++count;
}
memset(&fi,0,sizeof(FileInfo));
fi.size=statbuf.st_size;
fi.can_read =statbuf.st_mode&S_IROTH;
fi.can_write=statbuf.st_mode&S_IWOTH;
fi.is_hiddle=(entry->d_name[0]=='.');
fi.mtime=statbuf.st_mtime;
if(S_ISDIR(statbuf.st_mode))
{
fi.is_file=false;
fi.is_directory=true;
}
else
{
fi.is_file=true;
fi.is_directory=false;
}
strcpy(fi.name,HGL_MAX_PATH,entry->d_name);
if(config->folder_name.IsEmpty())
{
strcpy(fi.fullname,HGL_MAX_PATH,fi.name);
}
else
{
strcpy(fi.fullname,HGL_MAX_PATH,config->folder_name);
if(config->folder_name.GetEndChar()!=HGL_DIRECTORY_SEPARATOR)
strcat(fi.fullname,HGL_MAX_PATH,HGL_DIRECTORY_SEPARATOR);
strcat(fi.fullname,HGL_MAX_PATH,fi.name,HGL_MAX_PATH);
}
if(fi.is_directory)
{
EnumFileConfig *sub_efc=CreateSubConfig(config,fi);
if(sub_efc&&config->sub_folder)
{
sub_count=this->Enum(sub_efc);
if(sub_count>0)count+=sub_count;
}
ProcFolder(config,sub_efc,fi);
if(sub_efc)
delete sub_efc;
}
else
{
ProcFile(config,fi);
}
}
while((entry=hgl_readdir64(dir)));
closedir(dir);
chdir(path_buf);
return(count);
}
}//namespace filesystem
}//namespace hgl

24
src/UNIX/Exit.cpp Normal file
View File

@ -0,0 +1,24 @@
#include<hgl/platform/Exit.h>
#include<signal.h>
namespace hgl
{
static SignalAppExitFunc app_exit_func=nullptr;
void exit_signal_proc(int n,siginfo_t *si,void *)
{
}
void SetSignalAppExit(SignalAppExitFunc func)
{
if(!func)return;
app_exit_func=func;
struct sigaction act;
sigemptyset(&act.sa_mask); /** 清空阻塞信号 **/
act.sa_flags=SA_SIGINFO; /** 设置SA_SIGINFO 表示传递附加信息到触发函数 **/
act.sa_sigaction=exit_signal_proc;
}
}//namespace hgl

View File

@ -0,0 +1,43 @@
#include<hgl/platform/ExternalModule.h>
#include<hgl/platform/Platform.h>
#include<hgl/LogInfo.h>
#include<dlfcn.h>
namespace hgl
{
ExternalModule *LoadExternalModule(const os_char *filename)
{
ExternalModulePointer fp=dlopen(filename,RTLD_LAZY);
if(!fp)
{
LOG_ERROR(OS_TEXT("Load Module <")+OSString(filename)+OS_TEXT("> error! os info: ")+OSString(dlerror()));
return(nullptr);
}
return(new ExternalModule(fp));
}
/**
*
* @param name
* @return
*/
bool ExternalModule::Load(const os_char *name)
{
Clear();
fp=dlopen(name,RTLD_LAZY);
if(!fp)
{
LOG_ERROR(OS_TEXT("Load Module <")+OSString(name)+OS_TEXT("> error! os info: ")+OSString(dlerror()));
return(false);
}
return(true);
}
}//namespace hgl

24
src/UNIX/Fifo.cpp Normal file
View File

@ -0,0 +1,24 @@
#include<hgl/proc/Fifo.h>
#include<hgl/Str.h>
#include<sys/stat.h>
namespace hgl
{
/**
*
* @param fn ()
* @return
*/
bool Fifo::Create(const char *fn)
{
if(!fn||!(*fn))
return(false);
hgl::strcpy(filename,HGL_MAX_PATH-5,"/tmp/");
hgl::strcpy(filename+5,HGL_MAX_PATH-5,fn);
fd=mkfifo(filename,0777);
return(!fd);
}
}//namespace hgl

220
src/UNIX/File.cpp Normal file
View File

@ -0,0 +1,220 @@
#include<hgl/filesystem/FileSystem.h>
#include<hgl/LogInfo.h>
#include<hgl/io/FileInputStream.h>
#include<hgl/io/FileOutputStream.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
namespace hgl
{
namespace filesystem
{
constexpr int FILE_PROC_BUF_SIZE=HGL_SIZE_1MB;
/**
*
* @param sourcename
* @param targetname
* @return
*/
bool FileCopy(const OSString &targetname,const OSString &sourcename)
{
io::FileInputStream fis;
io::FileOutputStream fos;
if(!fis.Open(sourcename))return(false);
if(!fos.Create(targetname))return(false);
size_t buf_size=FILE_PROC_BUF_SIZE;
size_t length=fis.GetSize();
size_t cur;
if(buf_size>length)
buf_size=length;
SharedPtr<char> buf=new char[buf_size];
while(length)
{
if(length>buf_size)
cur=buf_size;
else
cur=length;
if(fis.Read(buf,cur))
if(fos.Write(buf,cur))
{
length-=cur;
continue;
}
return(false);
}
return(true);
}
/**
*
* @param filename
* @return
*/
bool FileDelete(const OSString &filename)
{
return(unlink(filename.c_str())==0);
}
/**
*
* @param sourcename
* @param targetname
* @return
*/
bool FileMove(const OSString &targetname,const OSString &sourcename)
{
if(FileCopy(sourcename,targetname))
return FileDelete(sourcename);
return(false);
}
/**
*
* @param oldname
* @param newname
* @return
*/
bool FileRename(const OSString &newname,const OSString &oldname)
{
return(rename(oldname.c_str(),
newname.c_str())==0);
}
/**
*
* @param filename
* @return
*/
bool FileExist(const OSString &filename)
{
return access(filename.c_str(),F_OK)>=0;
}
/**
*
* @param filename
*/
bool FileCanRead(const OSString &filename)
{
return access(filename.c_str(),R_OK)>=0;
}
/**
*
* @param filename
*/
bool FileCanWrite(const OSString &filename)
{
return access(filename.c_str(),W_OK)>=0;
}
/**
*
* @param filename
*/
bool FileCanExec(const OSString &filename)
{
return access(filename.c_str(),X_OK)>=0;
}
/**
*
* @param name
*/
bool IsDirectory(const os_char *name)
{
struct_stat64 buf;
memset(&buf,0,sizeof(struct_stat64));
if(hgl_lstat64(name,&buf)==-1)
return(false); //错误,有可能是不能访问
return S_ISDIR(buf.st_mode);
}
/**
*
*/
bool IsLink(const os_char *name)
{
struct_stat64 buf;
memset(&buf,0,sizeof(struct_stat64));
if(hgl_lstat64(name,&buf)==-1)
return(false); //错误,有可能是不能访问
return S_ISLNK(buf.st_mode);
}
bool MakeDirectory(const os_char *name)
{
if(!mkdir(name,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))return(true);
LOG_PROBLEM(OS_TEXT("Create Directory <")+OSString(name)+OS_TEXT("> failed,errno: ")+OSString(errno));
return(false);
}
os_char *GetRootPath(os_char *str)
{
if(str[0]==HGL_DIRECTORY_SEPARATOR)
return str+1;
else
return str;
}
/**
*
* @param name
* @return
*/
bool DeletePath(const OSString &name)
{
return rmdir(name.c_str());
}
/**
* <br>
*/
bool GetCurrentPath(OSString &path)
{
const int len=pathconf(".",_PC_PATH_MAX);
if(len<=0)return(false);
char *str=new char[len];
memset(str,0,len);
if(!getcwd(str,len))
{
delete[] str;
return(false);
}
path.Set(str,strlen(str),true);
return(true);
}
}//namespace filesystem
}//namespace hgl

69
src/UNIX/FileAccess.cpp Normal file
View File

@ -0,0 +1,69 @@
#include<hgl/io/FileAccess.h>
#include<hgl/LogInfo.h>
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<errno.h>
namespace hgl
{
namespace io
{
bool FileAccess::CreateTemp()
{
char template_filename[HGL_MAX_PATH]="/tmp/cm/XXXXXX";
fp=mkstemps(template_filename,HGL_MAX_PATH);
if(fp==-1)
return(false);
filename=template_filename;
mode=fomCreate;
return(true);
}
int OpenFile(const os_char *fn,FileOpenMode fom)
{
int fp;
if(fom==fomCreate )fp=hgl_open64(fn,O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);else
if(fom==fomCreateTrunc )fp=hgl_open64(fn,O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);else
if(fom==fomOnlyRead )fp=hgl_open64(fn,O_RDONLY );else
if(fom==fomOnlyWrite )fp=hgl_open64(fn,O_WRONLY );else
if(fom==fomReadWrite )fp=hgl_open64(fn,O_RDWR );else
if(fom==fomAppend )fp=hgl_open64(fn,O_APPEND );else
{
LOG_ERROR(OS_TEXT("UNIX,FileAccess,OpenFile(")+OSString(fn)+OS_TEXT(" mode error: "+OSString(fom)));
RETURN_ERROR(-1);
}
if(fp==-1)
{
LOG_ERROR(OS_TEXT("UNIX,FileAccess,OpenFile(")+OSString(fn)+OS_TEXT(") open return error: "+OSString(errno)));
}
return fp;
}
void CloseFile(int fp)
{
close(fp);
}
int64 FileAccess::Read(int64 offset,void *buf,int64 size)
{
if(!CanRead())return(-1);
return hgl_pread64(fp,buf,size,offset);
}
int64 FileAccess::Write(int64 offset,const void *buf,int64 size)
{
if(!CanWrite())return(-1);
return hgl_pwrite64(fp,buf,size,offset);
}
}//namespace io
}//namespace hgl

126
src/UNIX/LogConsole.cpp Normal file
View File

@ -0,0 +1,126 @@
#include<hgl/Logger.h>
#include<hgl/CodePage.h>
#include<hgl/thread/ThreadMutex.h>
#include<unistd.h>
#include<pthread.h>
#ifdef LOG_INFO_TIME
#include<hgl/Time.h>
#endif//LOG_INFO_TIME
namespace hgl
{
namespace logger
{
constexpr uint LOG_BUF_SIZE=4096;
/**
* unix控制台日志插件接口
*/
class LogUnixConsole:public Logger
{
char endline;
char log_buf[LOG_BUF_SIZE];
#ifdef LOGINFO_THREAD_MUTEX
ThreadMutex mutex;
#endif//LOGINFO_THREAD_MUTEX
public:
LogUnixConsole(LogLevel ll):Logger(ll)
{
endline='\n';
}
bool Create(const OSString &)
{
return(true);
}
void Close(){}
#ifdef LOG_INFO_THREAD
void WriteThreadID()
{
memcpy(log_buf,"[Thread:",8);
htos(log_buf+8,128-9,pthread_self());
strcat(log_buf,LOG_BUF_SIZE,']');
write(STDOUT_FILENO,log_buf,strlen(log_buf));
}
#endif//LOG_INFO_THREAD
#ifdef LOG_INFO_TIME
void WriteTime()
{
memcpy(log_buf,"[Time:",6);
ftos(log_buf+6,128-strlen(log_buf),GetDoubleTime());
strcat(log_buf,LOG_BUF_SIZE,']');
write(STDOUT_FILENO,log_buf,strlen(log_buf));
}
#endif//LOG_INFO_TIME
void Write(const u16char *str,int size)
{
#ifdef LOGINFO_THREAD_MUTEX
mutex.Lock();
#endif//LOGINFO_THREAD_MUTEX
#ifdef LOG_INFO_THREAD
WriteThreadID();
#endif//LOG_INFO_THREAD
#ifdef LOG_INFO_TIME
WriteTime();
#endif//LOG_INFO_TIME
int len;
len=u16_to_u8(log_buf,LOG_BUF_SIZE,str,size);
if(len>0)
{
log_buf[len++]='\n';
write(STDOUT_FILENO,log_buf,len);
}
#ifdef LOGINFO_THREAD_MUTEX
mutex.Unlock();
#endif//LOGINFO_THREAD_MUTEX
}
void Write(const char *str,int size)
{
#ifdef LOGINFO_THREAD_MUTEX
mutex.Lock();
#endif//LOGINFO_THREAD_MUTEX
#ifdef LOG_INFO_THREAD
WriteThreadID();
#endif//LOG_INFO_THREAD
#ifdef LOG_INFO_TIME
WriteTime();
#endif//LOG_INFO_TIME
write(STDOUT_FILENO,str,size);
write(STDOUT_FILENO,&endline,1);
#ifdef LOGINFO_THREAD_MUTEX
mutex.Unlock();
#endif//LOGINFO_THREAD_MUTEX
}
};//class LogInterface
Logger *CreateLoggerConsole(const OSString &,LogLevel ll)
{
if(ll<llError)
return(nullptr);
return(new LogUnixConsole(ll));
}
}//logger
}//namespace hgl

13
src/UNIX/Pipe.cpp Normal file
View File

@ -0,0 +1,13 @@
#include<hgl/proc/Pipe.h>
#include<unistd.h>
namespace hgl
{
bool CreatePipe(pipe_pair &pp)
{
if(pipe(pp)) // return 0 表示成功
return(false);
return true;
}
}//namespace hgl

62
src/UNIX/ProcMutex.cpp Normal file
View File

@ -0,0 +1,62 @@
#include<hgl/proc/ProcMutex.h>
#include<sys/fcntl.h>
#include<sys/stat.h>
#include<errno.h>
namespace hgl
{
ProcMutex::ProcMutex()
{
lock = nullptr;
}
bool ProcMutex::Create(const os_char *name)
{
if (lock != nullptr)return(false);
lock = sem_open(name, O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO, 1);
if(lock!=SEM_FAILED)
return(true);
lock = nullptr;
return(false);
}
void ProcMutex::Clear()
{
if (lock == nullptr)return;
sem_close(lock);
lock = nullptr;
}
bool ProcMutex::Lock()
{
if (lock == nullptr)return(false);
int err;
do
{
err = sem_wait(lock);
}
while (err && errno == EINTR);
return !err;
}
bool ProcMutex::TryLock()
{
if (lock == nullptr)return(false);
return(sem_trywait(lock)==0);
}
bool ProcMutex::Unlock()
{
if (lock == nullptr)return(false);
return(sem_post(lock)==0);
}
}//namespace hgl

85
src/UNIX/Process.cpp Normal file
View File

@ -0,0 +1,85 @@
#include<hgl/proc/Proc.h>
#include<hgl/filesystem/FileSystem.h>
#include<unistd.h>
#include<sys/wait.h>
#include<errno.h>
namespace hgl
{
using namespace filesystem;
bool Process::SetWorkPath(const OSString &wp)
{
if(!IsDirectory(wp))
return(false);
work_path=wp;
return(true);
}
bool Process::SetExecFile(const OSString &ef)
{
if(!FileCanExec(ef))
return(false);
filename=ef;
return(true);
}
bool Process::Execute()
{
pid=fork();
if(pid<0)
_exit(72); //为啥是72我也不清楚反正是要退出多少无所谓。抄的poco
if(pid==0)
{ //fork会复制出一个子进程并从这里开始执行
if(chdir(work_path.c_str())!=0)
_exit(72);
char **argv=new char *[args.GetCount()+2];
argv[0]=filename;
for(int i=0;i<args.GetCount();i++)
argv[i+1]=args[i].c_str();
argv[args.GetCount()+1]=0;
execvp(filename.c_str(),argv);
_exit(72);
}
else //原本的父进程
{
}
return(true);
}
bool Process::Wait()
{
if(pid<0)return(false);
int status;
int rc;
do
{
rc=waitpid(pid,&status,0);
}while(rc<0&&errno==EINTR);
return(true);
}
bool Process::Kill()
{
if(pid<0)return(false);
return !kill(pid,SIGKILL);
}
bool Process::RequestTerminate()
{
if(pid<0)return(false);
return !kill(pid,SIGINT);
}
}//namespace hgl

78
src/UNIX/ProgramPath.cpp Normal file
View File

@ -0,0 +1,78 @@
#include<hgl/type/BaseString.h>
#include<unistd.h>
#include<pwd.h>
#include<unistd.h>
namespace hgl
{
namespace filesystem
{
void GetLocalAppdataPath(os_char fn[HGL_MAX_PATH])
{
struct passwd pwd;
struct passwd *result;
char *buf;
size_t bufsize=sysconf(_SC_GETPW_R_SIZE_MAX);
if(bufsize==-1)
bufsize=16384;
buf=(char *)malloc(bufsize);
getpwuid_r(getuid(),&pwd,buf,bufsize,&result);
strcpy(fn,HGL_MAX_PATH,pwd.pw_dir);
free(buf);
}
/**
*
*/
bool GetCurrentProgram(OSString &result)
{
os_char *path=new os_char[HGL_MAX_PATH];
const int len=readlink("/proc/self/exe",path,HGL_MAX_PATH);
if(len<=0)
{
delete[] path;
return(false);
}
path[len]=0;
result.Set(path,len,true);
return(true);
}
/**
*
*/
bool GetCurrentProgramPath(OSString &result)
{
os_char *path=new os_char[HGL_MAX_PATH];
const int len=readlink("/proc/self/exe",path,HGL_MAX_PATH);
if(len<=0)
{
delete[] path;
return(false);
}
os_char *right=hgl::strrchr(path,len,HGL_DIRECTORY_SEPARATOR);
if(right)
*right=0;
else
path[len]=0;
result.Set(path,len,true);
return(true);
}
}//namespace filesystem
}//namespace hgl

51
src/UNIX/RWLock.cpp Normal file
View File

@ -0,0 +1,51 @@
#include<hgl/thread/RWLock.h>
#include<pthread.h>
namespace hgl
{
void GetWaitTime(struct timespec &,double);
RWLock::RWLock()
{
lock=new pthread_rwlock_t;
pthread_rwlock_init((pthread_rwlock_t *)lock,nullptr);
}
RWLock::~RWLock()
{
pthread_rwlock_destroy((pthread_rwlock_t *)lock);
}
bool RWLock::TryReadLock() {return !pthread_rwlock_tryrdlock((pthread_rwlock_t *)lock);}
#if HGL_OS != HGL_OS_macOS
bool RWLock::WaitReadLock(double t)
{
struct timespec abstime;
GetWaitTime(abstime,t);
return !pthread_rwlock_timedrdlock((pthread_rwlock_t *)lock,&abstime);
}
#endif//HGL_OS != HGL_OS_macOS
bool RWLock::ReadLock() {return !pthread_rwlock_rdlock((pthread_rwlock_t *)lock);}
bool RWLock::ReadUnlock() {return !pthread_rwlock_unlock((pthread_rwlock_t *)lock);}
bool RWLock::TryWriteLock() {return !pthread_rwlock_trywrlock((pthread_rwlock_t *)lock);}
#if HGL_OS != HGL_OS_macOS
bool RWLock::WaitWriteLock(double t)
{
struct timespec abstime;
GetWaitTime(abstime,t);
return !pthread_rwlock_timedwrlock((pthread_rwlock_t *)lock,&abstime);
}
#endif//HGL_OS != HGL_OS_macOS
bool RWLock::WriteLock() {return !pthread_rwlock_wrlock((pthread_rwlock_t *)lock);}
bool RWLock::WriteUnlock() {return !pthread_rwlock_unlock((pthread_rwlock_t *)lock);}
}//namespace hgl

87
src/UNIX/Semaphore.cpp Normal file
View File

@ -0,0 +1,87 @@
#include<hgl/thread/Semaphore.h>
#include<hgl/LogInfo.h>
#include<pthread.h>
#include<semaphore.h>
namespace hgl
{
void GetWaitTime(struct timespec &,double);
/**
* @param max_count
*/
Semaphore::Semaphore(int max_count)
{
ptr=new sem_t;
if(sem_init((sem_t *)ptr,PTHREAD_PROCESS_PRIVATE,0))
{
LOG_ERROR(OS_TEXT("sem_init error,max_count=")+OSString(max_count));
delete (sem_t *)ptr;
ptr=nullptr;
}
}
Semaphore::~Semaphore()
{
if(!ptr)return;
sem_destroy((sem_t *)ptr);
delete (sem_t *)ptr;
}
/**
*
* @param n
* @return
*/
bool Semaphore::Post(int n)
{
if(!ptr)return(false);
if(n<=0)return(false);
int result=0;
for(int i=0;i<n;i++)
result+=sem_post((sem_t *)ptr);
return !result;
//if(n==1)
// return !sem_post((sem_t *)ptr);
//else
// return !sem_post_multiple((sem_t *)ptr,n); //注这个函数不是所有os都支持
}
/**
*
* @return
*/
bool Semaphore::TryAcquire()
{
if(!ptr)return(false);
return !sem_trywait((sem_t *)ptr);
}
/**
*
* @param t ,使0.()
* @return ,,,false
*/
bool Semaphore::Acquire(double t)
{
if(!ptr)return(false);
if(t<=0)
return !sem_wait((sem_t *)ptr);
else
{
struct timespec abstime;
GetWaitTime(abstime,t);
return !sem_timedwait((sem_t *)ptr,&abstime);
}
}
}//namespace hgl

121
src/UNIX/SystemInfo.cpp Normal file
View File

@ -0,0 +1,121 @@
#include<hgl/platform/SystemInfo.h>
#include<hgl/platform/ConsoleSystemInitInfo.h>
#include<hgl/filesystem/FileSystem.h>
#include<pwd.h>
#include<unistd.h>
#include<signal.h>
#include<sys/resource.h>
namespace hgl
{
using namespace filesystem;
bool GetCMGDKPath(OSString &cmgdk_path)
{
constexpr char path_list[][18]=
{
"/usr/share/cmgdk",
"/usr/local/cmgdk"
};
char home_path[HGL_MAX_PATH];
struct passwd *pwd=getpwuid(getuid());
memset(home_path,0,sizeof(home_path));
strcpy(home_path,HGL_MAX_PATH,pwd->pw_dir);
strcat(home_path,HGL_MAX_PATH,"/cmgdk",6);
if(IsDirectory(home_path))
{
cmgdk_path=home_path;
return(true);
}
for(int i=0;i<sizeof(path_list)/sizeof(path_list[0]);i++)
{
if(IsDirectory(path_list[i]))
{
cmgdk_path=path_list[i];
return(true);
}
}
return(false);
}
void GetOSPath(CMGDKPATH &cp)
{
cp.os =OS_TEXT("/");
cp.osfont =OS_TEXT("/usr/share/fonts");
#if HGL_CPU == HGL_CPU_X86_64
cp.library =OS_TEXT("/usr/lib64");
#else
cp.library =OS_TEXT("/usr/lib");
#endif//HGL_CPU == HGL_CPU_X86_64
cp.common_data =OS_TEXT("/usr/share");
cp.local_data =OS_TEXT("/usr/local");
cp.temp =OS_TEXT("/tmp");
{
struct passwd pwd;
struct passwd *result;
char *buf;
size_t bufsize=sysconf(_SC_GETPW_R_SIZE_MAX);
if(bufsize==-1)
bufsize=16384;
buf=(char *)malloc(bufsize);
getpwuid_r(getuid(),&pwd,buf,bufsize,&result);
cp.mydata =pwd.pw_dir;
free(buf);
}
cp.myprogram =cp.mydata+OS_TEXT("/bin");
cp.mydesktop =cp.mydata+OS_TEXT("/Desktop");
}
bool SetLimit(int resource,int count)
{
struct rlimit64 rl;
getrlimit64(resource,&rl);
if(count<=rl.rlim_cur)
return(true);
if(count>rl.rlim_max)
rl.rlim_cur=rl.rlim_max;
else
rl.rlim_cur=count;
if(setrlimit64(resource,&rl))
{
LOG_ERROR(OS_TEXT("Set resource ")+OSString(resource)+OS_TEXT(" maximum value to ")+OSString((uint64)(rl.rlim_cur))+OS_TEXT(" failed."));
return(false);
}
return(true);
}
bool InitOSupport(ConsoleSystemInitInfo *sii)
{
if(sii->sig.pipe==false)
{
signal(SIGPIPE,SIG_IGN); //屏蔽管道信号,一般send/recv一个断开的Socket会触发此信号导致进程退出
}
if(!SetLimit(RLIMIT_NOFILE,sii->max_open_files))
return(false);
return(true);
}
}//namespace hgl

97
src/UNIX/Thread.cpp Normal file
View File

@ -0,0 +1,97 @@
#include<hgl/thread/Thread.h>
#include<hgl/thread/CondVar.h>
#include<hgl/LogInfo.h>
#include<signal.h>
#include<errno.h>
#include<hgl/Str.h>
namespace hgl
{
extern THREAD_FUNC ThreadFunc(Thread *tc);
/**
* (线)线
* @return 线
*/
bool Thread::Start()
{
if(tp)
{
LOG_ERROR(OS_TEXT("Thread::Start() error,tp!=nullptr."));
return(false);
}
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
exit_lock.Lock();
if(pthread_create(&tp,&attr,(void *(*)(void *))ThreadFunc,this)) //返回0表示正常
{
exit_lock.Unlock();
tp=0;
pthread_attr_destroy(&attr);
LOG_ERROR(OS_TEXT("Create Thread (pthread_create) failed.errno:")+OSString(errno));
return(false);
}
pthread_attr_destroy(&attr);
return(true);
}
/**
* 线
*/
bool Thread::IsCurThread()
{
if(!tp)
{
LOG_ERROR(OS_TEXT("Thread::IsCurThread() error,tp=nullptr."));
return(true);
}
return pthread_equal(pthread_self(),tp); //返回非0表示一致
}
void GetWaitTime(struct timespec &abstime,double t);
void WaitThreadExit(thread_ptr tp,const double &time_out)
{
if(!tp)
{
LOG_ERROR(OS_TEXT("WaitThreadExit error,tp=nullptr."));
return;
}
int retval;
void *res;
#if !defined(__ANDROID__)&&!defined(HGL_OS_BSD)
if(time_out>0)
{
struct timespec ts;
GetWaitTime(ts,time_out);
retval=pthread_timedjoin_np(tp,&res,&ts);
}
else
#endif//__ANDROID__&&BSD
{
retval=pthread_join(tp,&res);
}
#ifdef _DEBUG
char thread_addr[(sizeof(thread_ptr)<<1)+1];
DataToUpperHexStr(thread_addr,(uint8 *)&tp,sizeof(thread_ptr));
LOG_INFO(U8_TEXT("pthread_timedjoin_np/pthread_join [")+UTF8String(thread_addr)+U8_TEXT("] retval:")+UTF8String(retval));
#endif//_DEBUG
}
}//namespace hgl

67
src/UNIX/ThreadMutex.cpp Normal file
View File

@ -0,0 +1,67 @@
#include<hgl/thread/ThreadMutex.h>
#include<hgl/TypeFunc.h>
#include<pthread.h>
#include<sys/time.h>
namespace hgl
{
void GetWaitTime(struct timespec &,double);
ThreadMutex::ThreadMutex()
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutex_init(&ptr,&attr);
pthread_mutexattr_destroy(&attr);
}
ThreadMutex::~ThreadMutex()
{
pthread_mutex_destroy(&ptr);
}
/**
*
*
*/
void ThreadMutex::Lock()
{
pthread_mutex_lock(&ptr);
}
/**
*
* @return
*/
bool ThreadMutex::TryLock()
{
return(!pthread_mutex_trylock(&ptr));
}
#if !defined(__APPLE__)&&!defined(__ANDROID__)
/**
*
* @param time ,0
* @return
*/
bool ThreadMutex::WaitLock(double t)
{
struct timespec abstime;
GetWaitTime(abstime,t);
return !pthread_mutex_timedlock(&ptr, &abstime);
}
#endif//__APPLE__
/**
*
*/
void ThreadMutex::Unlock()
{
pthread_mutex_unlock(&ptr);
}
}//namespace hgl

102
src/UNIX/Time.cpp Normal file
View File

@ -0,0 +1,102 @@
#include<hgl/TypeFunc.h>
#include<sys/time.h>
namespace hgl
{
void GetWaitTime(struct timespec &abstime,double t)
{
clock_gettime(CLOCK_REALTIME,&abstime);
abstime.tv_sec+=t;
t-=(long)t;
abstime.tv_nsec+=t*HGL_NANO_SEC_PER_SEC;
if (abstime.tv_nsec >= HGL_NANO_SEC_PER_SEC)
{
abstime.tv_nsec -= HGL_NANO_SEC_PER_SEC;
++abstime.tv_sec;
}
}
}//namespace hgl
namespace hgl
{
/**
* get current timezone to GMT time offset
* @return time offset (second)
*/
long GetGMTOff()
{
tzset();
//return(-timezone); // linux ok,but BSD don't support
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo=localtime(&rawtime);
return timeinfo->tm_gmtoff;
}
/**
*
* @return ()
*/
uint64 GetTime()
{
// struct timeval tv;
// gettimeofday(&tv, nullptr);
// return ((tv.tv_sec) * HGL_MILLI_SEC_PRE_SEC) + (tv.tv_usec/1000);
struct timespec ts;
clock_gettime(CLOCK_REALTIME,&ts);
return (ts.tv_sec*HGL_MILLI_SEC_PRE_SEC)+(ts.tv_nsec/1000000);
}
/**
*
* @return ()
*/
uint64 GetMicroTime()
{
// struct timeval tv;
// gettimeofday(&tv, nullptr);
// return (tv.tv_sec) * HGL_MICRO_SEC_PER_SEC + tv.tv_usec;
struct timespec ts;
clock_gettime(CLOCK_REALTIME,&ts);
return (ts.tv_sec*HGL_MICRO_SEC_PER_SEC)+(ts.tv_nsec/1000);
}
/**
* ()
* @return ()
*/
double GetDoubleTime() ///<取得当前时间(双精度,单位秒)
{
// struct timeval tv;
// gettimeofday(&tv, nullptr);
// return double(tv.tv_sec) + (double(tv.tv_usec)/HGL_MICRO_SEC_PER_SEC);
struct timespec ts;
clock_gettime(CLOCK_REALTIME,&ts);
return double(ts.tv_sec)+double(ts.tv_nsec)/HGL_NANO_SEC_PER_SEC;
}
/**
*
* @param time ()
*/
void WaitTime(double t)
{
if(t<=0)return;
struct timeval tv;
tv.tv_sec = t;
tv.tv_usec = (t-tv.tv_sec)*HGL_MICRO_SEC_PER_SEC;
select(0, nullptr, nullptr, nullptr, &tv);
//注不要使用sleep/nanosleep/clock_nanosleep来代替select因为它们是真正的暂停执行线程。而sleep是挂起等待可以被信号打断
}
}//namespace hgl

30
src/UNIX/XCBVulkan.cpp Normal file
View File

@ -0,0 +1,30 @@
#include<hgl/platform/Vulkan.h>
#include"XCBWindow.h"
#include<vulkan/vulkan_xcb.h>
namespace hgl
{
VkSurfaceKHR CreateVulkanSurface(VkInstance vk_inst,Window *w)
{
if(vk_inst==VK_NULL_HANDLE)return(VK_NULL_HANDLE);
if(!w)return(VK_NULL_HANDLE);
XCBWindow *win=(XCBWindow *)w;
VkXcbSurfaceCreateInfoKHR createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.connection = win->GetConnection();
createInfo.window = win->GetWindow();
VkSurfaceKHR surface;
VkResult res = vkCreateXcbSurfaceKHR(vk_inst, &createInfo, nullptr, &surface);
if (res != VK_SUCCESS)
return(VK_NULL_HANDLE);
return(surface);
}
}//namespace hgl

110
src/UNIX/XCBWindow.cpp Normal file
View File

@ -0,0 +1,110 @@
#include"XCBWindow.h"
namespace hgl
{
bool XCBWindow::InitConnection()
{
int scr;
connection=xcb_connect(nullptr,&scr);
if(!connection||xcb_connection_has_error(connection))
return(false);
const xcb_setup_t *setup=xcb_get_setup(connection);
xcb_screen_iterator_t iter=xcb_setup_roots_iterator(setup);
while(scr-->0)xcb_screen_next(&iter);
screen=iter.data;
return(true);
}
XCBWindow::XCBWindow(const UTF8String &wn):Window(wn)
{
connection=nullptr;
screen=nullptr;
atom_wm_delete_window=nullptr;
}
XCBWindow::~XCBWindow()
{
}
bool XCBWindow::Create(uint w,uint h)
{
if(w<=0||h<=0)return(false);
if(!InitConnection())return(false);
window=xcb_generate_id(connection);
uint32_t value_mask,value_list[32];
value_mask=XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
value_list[0] = screen->black_pixel;
value_list[1] = XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_EXPOSURE;
width=w;
height=h;
xcb_create_window(connection, XCB_COPY_FROM_PARENT, window, screen->root, 0,0, width, height, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, value_mask, value_list);
xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection, 1, 12, "WM_PROTOCOLS");
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, cookie, 0);
xcb_intern_atom_cookie_t cookie2 = xcb_intern_atom(connection, 0, 16, "WM_DELETE_WINDOW");
atom_wm_delete_window = xcb_intern_atom_reply(connection, cookie2, 0);
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, (*reply).atom, 4, 32, 1,
&(*atom_wm_delete_window).atom);
free(reply);
xcb_change_property (connection, XCB_PROP_MODE_REPLACE, window,XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
win_name.Length(), win_name.c_str());
xcb_map_window(connection, window);
const uint32_t coords[] =
{
(screen->width_in_pixels-width)/2,
(screen->height_in_pixels-height)/2
};
xcb_configure_window(connection, window, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, coords);
xcb_flush(connection);
xcb_generic_event_t *e;
while ((e = xcb_wait_for_event(connection))) {
if ((e->response_type & ~0x80) == XCB_EXPOSE) break;
}
}
void XCBWindow::Close()
{
xcb_destroy_window(connection,window);
xcb_disconnect(connection);
}
void XCBWindow::SetCaption(const OSString &caption)
{
win_name=caption;
xcb_change_property (connection, XCB_PROP_MODE_REPLACE, window,XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
win_name.Length(), win_name.c_str());
}
bool XCBWindow::MessageProc()
{
return(true);
}
bool XCBWindow::WaitMessage()
{
return(true);
}
Window *CreateRenderWindow(const UTF8String &win_name)
{
return(new XCBWindow(win_name));
}
void InitNativeWindowSystem(){}
}//namespace hgl

39
src/UNIX/XCBWindow.h Normal file
View File

@ -0,0 +1,39 @@
#include<hgl/platform/Window.h>
#include<xcb/xcb.h>
#include<xcb/xcb_atom.h>
namespace hgl
{
class XCBWindow:public Window
{
xcb_connection_t *connection;
xcb_screen_t *screen;
xcb_window_t window;
xcb_intern_atom_reply_t *atom_wm_delete_window;
private:
bool InitConnection();
VkSurfaceKHR CreateSurface(VkInstance) override;
public:
XCBWindow(const UTF8String &wn);
~XCBWindow();
bool Create(uint w,uint h)override;
bool Create(uint,uint,uint)override{}
void Close()override;
xcb_connection_t *GetConnection(){return connection;}
xcb_screen_t *GetScreen(){return screen;}
xcb_window_t GetWindow(){return window;}
void SetCaption(const OSString &caption) override;
void Show()override{}
void Hide()override{}
bool MessageProc() override;
bool WaitMessage() override;
};//class XCBWindow:public Window
}//namespace hgl

43
src/Win/Clipboard.cpp Normal file
View File

@ -0,0 +1,43 @@
#include<windows.h>
#include<shobjidl.h>
namespace hgl
{
namespace os
{
void CopyTextToClipboard(const u16char *str)
{
if(!str||!(*str))return;
if (!OpenClipboard(nullptr))return;
EmptyClipboard();
HGLOBAL clipbuffer;
u16char * buffer;
clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(str)+1);
buffer = (u16char *)GlobalLock(clipbuffer);
strcpy(buffer, str);
GlobalUnlock(clipbuffer);
SetClipboardData(CF_UNICODETEXT, clipbuffer);
CloseClipboard();
}
const u16char *GetTextFromClipboard()
{
if (!OpenClipboard(nullptr))
return 0;
u16char * buffer = 0;
HANDLE hData = GetClipboardData( CF_UNICODETEXT );
buffer = (u16char *)GlobalLock( hData );
GlobalUnlock( hData );
CloseClipboard();
return buffer;
}
}//namespace os
}//namespace hgl

61
src/Win/CodePage.cpp Normal file
View File

@ -0,0 +1,61 @@
#include<hgl/CodePage.h>
#include<windows.h>
namespace hgl
{
int to_utf16(const CharSet &cs,u16char **dst,const char *src,const int src_size)
{
const int src_str_size=(src_size==-1)?strlen(src):src_size;
const int len=MultiByteToWideChar(cs.codepage,0,src,src_str_size,0,0);
if(len<=0)return(len);
*dst=new u16char[len];
return MultiByteToWideChar(cs.codepage,0,src,src_str_size,*dst,len);
}
int to_utf8(const CharSet &cs,char **dst,const char *src,const int src_size)
{
u16char *u16str;
int u16size=to_utf16(cs,&u16str,src,src_size);
if(u16size<=0)return(u16size);
int u8_size;
*dst = u16_to_u8(u16str, u16size, u8_size);
delete[] u16str;
return u8_size;
}
int utf16_to(const CharSet &cs,char **dst,const u16char *src,const int src_size)
{
const int src_str_size=(src_size==-1)?strlen(src):src_size;
const int len=WideCharToMultiByte(cs.codepage,0,src,src_str_size,0,0,0,0);
if(len<=0)return(len);
*dst=new char[len];
return WideCharToMultiByte(cs.codepage,0,src,src_str_size,*dst,len,0,0);
}
int utf8_to(const CharSet &cs,char **dst,const char *src,const int src_size)
{
int u16str_size;
u16char *u16str=u8_to_u16(src,src_size,u16str_size);
if(!u16str)return(0);
int result=utf16_to(cs,dst,u16str,u16str_size);
delete[] u16str;
return(result);
}
}//namespace hgl

38
src/Win/CondVar.cpp Normal file
View File

@ -0,0 +1,38 @@
#include<hgl/thread/CondVar.h>
#include<hgl/thread/ThreadMutex.h>
#include<hgl/thread/RWLock.h>
#pragma warning(disable:4800) // BOOL -> bool 性能损失警告
namespace hgl
{
CondVar::CondVar()
{
cond_var = new CONDITION_VARIABLE;
InitializeConditionVariable((CONDITION_VARIABLE *)cond_var);
}
CondVar::~CondVar()
{
delete (CONDITION_VARIABLE *)cond_var;
}
bool CondVar::Wait(ThreadMutex *tm, double time)
{
return SleepConditionVariableCS((CONDITION_VARIABLE *)cond_var,(CRITICAL_SECTION *)(tm->GetThreadMutex()),(DWORD)(time>0?time*1000:INFINITE));
}
bool CondVar::Wait(RWLock *lock, double time, bool read)
{
return SleepConditionVariableSRW((CONDITION_VARIABLE *)cond_var,(SRWLOCK *)(lock->GetRWLock()),(DWORD)(time>0?time*1000:INFINITE),read?CONDITION_VARIABLE_LOCKMODE_SHARED:0);
}
void CondVar::Signal()
{
WakeConditionVariable((CONDITION_VARIABLE *)cond_var);
}
void CondVar::Broadcast()
{
WakeAllConditionVariable((CONDITION_VARIABLE *)cond_var);
}
}//namespace hgl

154
src/Win/DateTime.cpp Normal file
View File

@ -0,0 +1,154 @@
#include<hgl/type/DataType.h>
#include<hgl/type/DateTime.h>
#include<hgl/io/DataInputStream.h>
#include<hgl/io/DataOutputStream.h>
#include<hgl/thread/RWLock.h>
#include<time.h>
namespace hgl
{
namespace
{
#define APR_DELTA_EPOCH_IN_USEC 11644473600000000 //转Windows时间到Unix时间的一个差值
//Windows是1601.1.1
//Unix是1970.1.1
//tanks for APR
static inline void SystemTimeToMicroTime(uint64 *result, SYSTEMTIME *st_input)
{
FILETIME ft;
SystemTimeToFileTime(st_input, &ft);
/* Convert FILETIME one 64 bit number so we can work with it. */
*result = ft.dwHighDateTime;
*result = (*result) << 32;
*result |= ft.dwLowDateTime;
*result /= 10; /* Convert from 100 nano-sec periods to micro-seconds. */
*result -= APR_DELTA_EPOCH_IN_USEC; /* Convert from Windows epoch to Unix epoch */
return;
}
static inline void MicroTimeToFileTime(LPFILETIME pft, uint64 t)
{
LONGLONG ll;
t += APR_DELTA_EPOCH_IN_USEC;
ll = t * 10;
pft->dwLowDateTime = (DWORD)ll;
pft->dwHighDateTime = (DWORD)(ll >> 32);
return;
}
static inline void MicroTimeToSystemTime(LPSYSTEMTIME pst, uint64 t)
{
FILETIME ft;
MicroTimeToFileTime(&ft, t);
FileTimeToSystemTime(&ft, pst);
}
}
}//namespace hgl
namespace hgl
{
//和系统时间同步
void Time::Sync(const double cur_time)
{
uint64 st64;
uint64 lt64;
SYSTEMTIME st;
SYSTEMTIME local_time;
TIME_ZONE_INFORMATION time_zone;
if (cur_time <= 0)
{
GetSystemTime(&st);
SystemTimeToMicroTime(&st64, &st);
}
else
{
st64 = cur_time*HGL_MICRO_SEC_PER_SEC;
MicroTimeToSystemTime(&st, st64);
}
GetTimeZoneInformation(&time_zone);
SystemTimeToTzSpecificLocalTime(&time_zone, &st, &local_time);
hours = local_time.wHour;
minutes = local_time.wMinute;
seconds = local_time.wSecond;
micro_seconds = local_time.wMilliseconds * 1000;
week_day = local_time.wDayOfWeek;
SystemTimeToMicroTime(&lt64, &local_time);
gmt_off = lt64 - st64;
}
}//namespace hgl
//--------------------------------------------------------------------------------------------------
namespace hgl
{
void Date::Sync(const double cur_time)
{
SYSTEMTIME st;
if (cur_time <= 0)
GetLocalTime(&st);
else
MicroTimeToSystemTime(&st, cur_time*HGL_MICRO_SEC_PER_SEC);
year = st.wYear;
month = st.wMonth;
day = st.wDay;
week_day = st.wDayOfWeek;
}
}//namespace hgl
namespace hgl
{
void ToDateTime(Date &d,Time &t,const double cur_time)
{
FILETIME ft,local_ft;
SYSTEMTIME st;
MicroTimeToFileTime(&ft, cur_time*HGL_MICRO_SEC_PER_SEC);
FileTimeToSystemTime(&ft, &st);
FileTimeToLocalFileTime(&ft, &local_ft);
d.Set(st.wYear, st.wMonth, st.wDay, st.wDayOfWeek);
t.Set(st.wHour, st.wMinute, st.wSecond, st.wMilliseconds * 1000, st.wDayOfWeek);
t.SetGMT((local_ft.dwLowDateTime - ft.dwLowDateTime) / 10);
}
double FromDateTime(const int year,const int month,const int day,
const int hour,const int minute,const int second,const int micro_second,
const int gmt_off)
{
SYSTEMTIME st;
st.wYear = year;
st.wMonth = month;
st.wDay = day;
st.wDayOfWeek = 0;
st.wHour = hour;
st.wMinute = minute;
st.wSecond = second;
st.wMilliseconds = micro_second / 1000;
uint64 result;
SystemTimeToMicroTime(&result, &st);
result -= gmt_off;
return(double(result) / HGL_MICRO_SEC_PER_SEC);
}
}//namespace hgl

141
src/Win/Desktop.cpp Normal file
View File

@ -0,0 +1,141 @@
#include<hgl/type/DataType.h>
#include<hgl/type/BaseString.h>
#include<hgl/filesystem/FileSystem.h>
#include<hgl/Desktop.h>
#include<shobjidl.h>
namespace hgl
{
namespace os
{
/**
* ,: PopupWebBrowser(L"http://www.hyzgame.com.cn");
* @param url
*/
void PopupWebBrowser(const wchar_t *url)
{
ShellExecuteW(nullptr,nullptr,url,nullptr,nullptr,0);
}
/**
* ,email地址: PopupEmailClient(L"hyz@hyzgame.com.cn",L"您好!");
* @param email
* @param subject
*/
void PopupEmailClient(const WideString &email,const WideString &subject)
{
wchar_t url[MAX_PATH]=L"mailto:";
strcat(url, MAX_PATH, email);
const wchar_t subject_header[] = L"?Subject=\"";
const size_t subject_header_size = sizeof(subject_header)/sizeof(wchar_t);
strcat(url, MAX_PATH, subject_header, subject_header_size);
strcat(url, MAX_PATH, subject);
strcat(url, MAX_PATH, L'\"');
ShellExecuteW(nullptr,nullptr,url,nullptr,nullptr,0);
}
/**
*
* @param sc
* @return
*/
bool CreateShortCut(const ShortCut &sc)
{
IShellLinkW *psl=nullptr;
IPersistFile *pPf=nullptr;
WideString lnk_filename=sc.lnk_filename;
lnk_filename += L".lnk";
HRESULT hresult;
hresult=CoCreateInstance(CLSID_ShellLink,nullptr,CLSCTX_INPROC_SERVER,IID_IShellLinkW,(LPVOID*)&psl);
if(hresult!=S_OK)
return(false);
hresult=psl->QueryInterface(IID_IPersistFile,(LPVOID*)&pPf);
if(hresult!=S_OK)
return(false);
if(!sc.work_directory.IsEmpty())
{
hresult=psl->SetWorkingDirectory(sc.work_directory.c_str());
if(hresult!=S_OK)
return(false);
}
if(!sc.param.IsEmpty())
{
hresult=psl->SetArguments(sc.param.c_str());
if(hresult!=S_OK)
return(false);
}
hresult=psl->SetPath(sc.filename.c_str());
if(hresult!=S_OK)
return(false);
if(!sc.icon_filename.IsEmpty())
if(filesystem::FileExist(sc.icon_filename))
{
hresult=psl->SetIconLocation(sc.icon_filename.c_str(),0);
if(hresult!=S_OK)
return(false);
}
if(!sc.descript.IsEmpty())
{
hresult=psl->SetDescription(sc.descript.c_str());
if(hresult!=S_OK)
return(false);
}
hresult=pPf->Save(lnk_filename.c_str(),TRUE);
if(hresult!=S_OK)
return(false);
if(pPf)
pPf->Release();
if(psl)
psl->Release();
return true;
}
//#if (NTDDI_VERSION >= NTDDI_VISTA)
// /**
// * 取得文件图标
// * @param filename 文件名
// * @param width 图标宽度
// * @param height 图标高度
// * @param color 图标色彩数
// * @return 图标象素数据(请自行delete[],另返回NULL表示失败)
// */
// void *GetFileIcon(const wchar_t *filename,int &width,int &height,int &color)
// {
// IShellItemImageFactory *pShellItemImageFactory = nullptr;
// IBindCtx *m_pBindContext;
//
// //该函数要求ie7.0,但无法确定
// if(SHCreateItemFromParsingName(filename
// m_pBindContext,
// IID_PPV_ARGS(&pShellItemImageFactory)
// )!=S_OK)return(false);
// }
//#endif//NTDDI_VERSION >= NTDDI_VISTA
}//namespace os
}//namespace hgl

131
src/Win/EnumFile.cpp Normal file
View File

@ -0,0 +1,131 @@
#include<hgl/filesystem/EnumFile.h>
#include<hgl/LogInfo.h>
#include<windows.h>
#include<sys/types.h>
namespace hgl
{
namespace filesystem
{
/**
*
* @param config
* @return ,<0
*/
int EnumFile::Enum(EnumFileConfig *config)
{
if(!config)RETURN_ERROR(-1);
if(config->folder_name.IsEmpty()
&&config->find_name.IsEmpty())RETURN_ERROR(-4);
OSString full_findname;
int count=0;
if(config->folder_name.IsEmpty())
{
full_findname=config->find_name;
}
else
{
full_findname=MergeFilename(config->folder_name,config->find_name);
}
WIN32_FIND_DATAW FindFileData;
HANDLE hFind;
hFind = FindFirstFileW(full_findname, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
return(-1);
FileInfo fi;
int sub_count;
do
{
if(strcmp(FindFileData.cFileName,OS_TEXT("."))==0
|| strcmp(FindFileData.cFileName,OS_TEXT(".."))==0)
{
continue;
}
if(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
{
if(!config->proc_folder)continue;
}
else
{
if(!config->proc_file)continue;
++count;
}
memset(&fi,0,sizeof(FileInfo));
strcpy(fi.name,HGL_MAX_PATH,FindFileData.cFileName);
if(config->folder_name.IsEmpty())
{
strcpy(fi.fullname, HGL_MAX_PATH, fi.name);
}
else
{
strcpy(fi.fullname, HGL_MAX_PATH, config->folder_name);
if(config->folder_name.GetEndChar()!=HGL_DIRECTORY_SEPARATOR)
strcat(fi.fullname, HGL_MAX_PATH, HGL_DIRECTORY_SEPARATOR);
const int rp =config->find_name.FindChar(HGL_DIRECTORY_SEPARATOR);//防止查询名称内仍有路径
if(rp!=-1)
strcat(fi.fullname, HGL_MAX_PATH,config->find_name.c_str(),rp);
strcat(fi.fullname, HGL_MAX_PATH, fi.name, HGL_MAX_PATH);
}
fi.size = FindFileData.nFileSizeHigh;
fi.size <<= 32;
fi.size |= FindFileData.nFileSizeLow;
fi.is_hiddle=FindFileData.dwFileAttributes&FILE_ATTRIBUTE_HIDDEN;
fi.can_read =true;
fi.can_write=!(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_READONLY);
fi.mtime=*(uint64 *)&FindFileData.ftLastWriteTime;
if(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
{
fi.is_file=false;
fi.is_directory=true;
EnumFileConfig *sub_efc=CreateSubConfig(config,fi);
if(sub_efc&&config->sub_folder)
{
sub_count=this->Enum(sub_efc);
if(sub_count>0)count+=sub_count;
}
ProcFolder(config,sub_efc,fi);
if(sub_efc)
delete sub_efc;
}
else
{
fi.is_file=true;
fi.is_directory=false;
ProcFile(config,fi);
}
}
while(FindNextFileW(hFind, &FindFileData));
FindClose(hFind);
return(count);
}
}//namespace filesystem
}//namespace hgl

89
src/Win/EnumVolume.cpp Normal file
View File

@ -0,0 +1,89 @@
#include<hgl/filesystem/EnumVolume.h>
#include<hgl/type/BaseString.h>
#include<hgl/LogInfo.h>
#include<windows.h>
namespace hgl
{
namespace filesystem
{
int EnumVolume(List<VolumeInfo> &vi_list,const VolumeCheckConfig &cfg)
{
if(cfg.isErrorConfig())
return(-1);
HANDLE handle;
u16char volume_name[HGL_MAX_PATH+1];
u16char path_name[HGL_MAX_PATH];
int count=0;
handle=FindFirstVolumeW(volume_name,HGL_MAX_PATH);
if(handle==INVALID_HANDLE_VALUE)return(-2);
do
{
hgl::filesystem::VolumeInfo vi;
memset(&vi,0,sizeof(hgl::filesystem::VolumeInfo));
DWORD length;
GetVolumePathNamesForVolumeNameW(volume_name,path_name,HGL_MAX_PATH,&length); //这个函数要win xp/2003才能用
path_name[length]=0;
hgl::strcpy(vi.name,HGL_MAX_PATH,volume_name);
hgl::strcpy(vi.path,HGL_MAX_PATH,path_name);
UINT type=GetDriveTypeW(path_name);
if(type==DRIVE_REMOVABLE){ if(!cfg.removable )continue;vi.driver_type=hgl::filesystem::VolumeInfo::dtRemovable; }else
if(type==DRIVE_FIXED ){ if(!cfg.fixed )continue;vi.driver_type=hgl::filesystem::VolumeInfo::dtFixed; }else
if(type==DRIVE_REMOTE ){ if(!cfg.remote )continue;vi.driver_type=hgl::filesystem::VolumeInfo::dtRemote; }else
if(type==DRIVE_RAMDISK ){ if(!cfg.ram_disk )continue;vi.driver_type=hgl::filesystem::VolumeInfo::dtRamDisk; }else
if(type==DRIVE_CDROM ){ if(!cfg.cdrom )continue;vi.driver_type=hgl::filesystem::VolumeInfo::dtCDROM; }else
{
if(cfg.unknow)vi.driver_type=hgl::filesystem::VolumeInfo::dtNone;
continue;
}
uint32 file_system_flags;
if(GetVolumeInformationW(path_name,
vi.volume_label,
255,
(unsigned long *)&vi.serial,
(unsigned long *)&vi.filename_max_length,
(unsigned long *)&file_system_flags,
vi.file_system,
255))
{
vi.unicode=file_system_flags&FILE_UNICODE_ON_DISK;
}
else
{
LOG_PROBLEM(U16_TEXT("Get <")+UTF16String(path_name)+U16_TEXT("> info failedWindows error code: ")+UTF16String((uint)GetLastError()));
}
if(GetDiskFreeSpaceExW(path_name,
(ULARGE_INTEGER *)&vi.available_space,
(ULARGE_INTEGER *)&vi.total_space,
(ULARGE_INTEGER *)&vi.free_space))
{
vi_list.Add(vi);
}
else
{
LOG_PROBLEM(U16_TEXT("Get disk free space <")+UTF16String(path_name)+U16_TEXT("> data failed,Windows error code: ")+UTF16String((uint)GetLastError()));
}
count++;
} while(FindNextVolumeW(handle,volume_name,HGL_MAX_PATH));
FindVolumeClose(handle);
return(count);
}
}//namespace filesystem
}//namespace hgl

View File

@ -0,0 +1,54 @@
#include<hgl/platform/ExternalModule.h>
#include<hgl/platform/Platform.h>
#include<hgl/LogInfo.h>
namespace hgl
{
ExternalModule *LoadExternalModule(const os_char *filename)
{
ExternalModulePointer fp=LoadLibraryW(filename);
if(!fp)
{
uint dw=GetLastError();
os_char *str=nullptr;
FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,nullptr,dw,
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),str,0,nullptr);
LOG_ERROR(OS_TEXT("LoadModule <")+OSString(filename)+OS_TEXT("> error! os info: ")+OSString(dw)+OSString::charOf(',')+str);
return(nullptr);
}
return(new ExternalModule(fp));
}
/**
*
* @param name
* @return
*/
bool ExternalModule::Load(const os_char *name)
{
Clear();
fp=LoadLibraryW(name);
if(!fp)
{
const uint dw=GetLastError();
u16char *str=nullptr;
FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,nullptr,dw,
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),str,0,nullptr);
LOG_ERROR(L"LoadModule <"+UTF16String(name)+L"> error! os info: "+UTF16String(dw)+UTF16String::charOf(L',')+str);
return(false);
}
return(true);
}
}//namespace hgl

0
src/Win/Fifo.cpp Normal file
View File

217
src/Win/File.cpp Normal file
View File

@ -0,0 +1,217 @@
#include<hgl/filesystem/FileSystem.h>
#include<hgl/LogInfo.h>
#include<hgl/io/FileInputStream.h>
#include<hgl/io/FileOutputStream.h>
#include <windows.h>
#include <sys/types.h>
#include <string.h>
namespace hgl
{
namespace filesystem
{
constexpr int FILE_PROC_BUF_SIZE=HGL_SIZE_1MB;
/**
*
* @param sourcename
* @param targetname
* @return
*/
bool FileCopy(const OSString &targetname,const OSString &sourcename)
{
return(::CopyFileW(sourcename,targetname,false));
}
/**
*
* @param filename
* @return
*/
bool FileDelete(const OSString &filename)
{
return(::DeleteFileW(filename));
}
/**
*
* @param sourcename
* @param targetname
* @return
*/
bool FileMove(const OSString &targetname,const OSString &sourcename)
{
return(::MoveFileW(sourcename,targetname));
}
/**
*
* @param oldname
* @param newname
* @return
*/
bool FileRename(const OSString &newname,const OSString &oldname)
{
return(::MoveFileW(oldname,newname));
}
/**
*
* @param filename
* @return
*/
bool FileExist(const OSString &filename)
{
WIN32_FIND_DATAW wfd;
HANDLE hFind;
hFind=FindFirstFileW(filename, &wfd);
if(hFind==INVALID_HANDLE_VALUE)
return(false);
FindClose(hFind);
return(true);
}
/**
*
* @param filename
*/
bool FileCanRead(const OSString &filename)
{
const DWORD attr=GetFileAttributesW(filename);
if(attr==INVALID_FILE_ATTRIBUTES)
return(false);
if(attr&(FILE_ATTRIBUTE_DEVICE|FILE_ATTRIBUTE_DIRECTORY)) //不是个文件
return(false);
if(attr&FILE_ATTRIBUTE_OFFLINE)
return(false);
return(true);
}
/**
*
* @param filename
*/
bool FileCanWrite(const OSString &filename)
{
const DWORD attr=GetFileAttributesW(filename);
if(attr==INVALID_FILE_ATTRIBUTES)
return(false);
if(attr&(FILE_ATTRIBUTE_DEVICE|FILE_ATTRIBUTE_DIRECTORY)) //不是个文件
return(false);
if(attr&FILE_ATTRIBUTE_OFFLINE)
return(false);
return (attr&FILE_ATTRIBUTE_READONLY)?false:true;
}
/**
*
* @param filename
*/
bool FileCanExec(const OSString &filename)
{
int index = filename.FindRightChar('.');
if (index == -1)return(false);
if (index > filename.Length() - 4)
return(false);
const os_char *ext = filename.c_str() + index + 1;
if (!ext)return(false);
if (stricmp(ext, "exe") == 0)return(true);
if (stricmp(ext, "com") == 0)return(true);
if (stricmp(ext, "bat") == 0)return(true);
if (stricmp(ext, "msi") == 0)return(true);
if (stricmp(ext, "msp") == 0)return(true);
return(false);
}
/**
*
* @param name
*/
bool IsDirectory(const os_char *name)
{
DWORD attrib = GetFileAttributesW(name);
if (attrib == INVALID_FILE_ATTRIBUTES)
return(false);
return attrib&FILE_ATTRIBUTE_DIRECTORY;
}
bool MakeDirectory(const os_char *name)
{
if(::CreateDirectoryW(name,nullptr))return(true);
const uint win_error=GetLastError();
LOG_PROBLEM(OS_TEXT("Create Directory <")+OSString(name)+OS_TEXT("> failed,errno: ")+OSString(win_error));
return(false);
}
os_char *GetRootPath(os_char *str)
{
if(str[1]==OS_TEXT(':'))
return str+3;
return str;
}
/**
*
* @param name
* @return
*/
bool DeletePath(const OSString &name)
{
return(RemoveDirectoryW(name));
}
/**
* <br>
*/
bool GetCurrentPath(OSString &path)
{
int len;
u16char *dir;
len=GetCurrentDirectoryW(0,nullptr);
if(len==0)
return(nullptr);
dir=new u16char[len+1];
if(GetCurrentDirectoryW(len,dir))
{
if(len==3&&dir[1]==OS_TEXT(':'))
len=2; //如果是"C:\"这种情况,去掉"\"
dir[len]=0;
path.Set(dir,len,true);
return(true);
}
delete[] dir;
return(false);
}
}//namespace filesystem
}//namespace hgl

68
src/Win/FileAccess.cpp Normal file
View File

@ -0,0 +1,68 @@
#include<hgl/io/FileAccess.h>
#include<hgl/LogInfo.h>
#include<io.h>
#include<share.h>
#include<fcntl.h>
namespace hgl
{
namespace io
{
bool FileAccess::CreateTemp()
{
const uint buf_size=HGL_MAX_PATH;
u16char PathBuffer[buf_size];
u16char TempName[buf_size];
GetTempPathW(buf_size,PathBuffer);
GetTempFileNameW(PathBuffer,L"NEW",0,TempName);
return Open(TempName,fomCreate);
}
int OpenFile(const os_char *fn,FileOpenMode fom)
{
int fp;
errno_t result;
if(fom==fomCreate )result=_wsopen_s(&fp,fn,_O_BINARY|_O_WRONLY|_O_CREAT ,_SH_DENYNO,S_IREAD|_S_IWRITE);else
if(fom==fomCreateTrunc )result=_wsopen_s(&fp,fn,_O_BINARY|_O_WRONLY|_O_CREAT|_O_TRUNC ,_SH_DENYNO,S_IREAD|_S_IWRITE);else
// if(fom==fomCreateTemp )result=_wsopen_s(&fp,fn,_O_BINARY|_O_WRONLY|_O_CREAT|_O_TEMPORARY ,_SH_DENYNO,S_IREAD|_S_IWRITE);else //某些平台不支持所以全都不使用fomCreateTemp,统一使用CreateTemp
if(fom==fomOnlyRead )result=_wsopen_s(&fp,fn,_O_BINARY|_O_RDONLY ,_SH_DENYNO,S_IREAD|_S_IWRITE);else
if(fom==fomOnlyWrite )result=_wsopen_s(&fp,fn,_O_BINARY|_O_WRONLY ,_SH_DENYNO,S_IREAD|_S_IWRITE);else
if(fom==fomReadWrite )result=_wsopen_s(&fp,fn,_O_BINARY|_O_RDWR ,_SH_DENYNO,S_IREAD|_S_IWRITE);else
if(fom==fomAppend )result=_wsopen_s(&fp,fn,_O_BINARY|_O_APPEND ,_SH_DENYNO,S_IREAD|_S_IWRITE);else
RETURN_ERROR(-1);
return(fp);
}
void CloseFile(int fp)
{
_close(fp);
}
int64 FileAccess::Read(int64 offset,void *buf,int64 size)
{
if(!CanRead())return(-1);
if(_lseeki64(fp,offset,(int)SeekOrigin::Begin)==offset)
return _read(fp,buf,size);
else
return -1;
}
int64 FileAccess::Write(int64 offset,const void *buf,int64 size)
{
if(!CanWrite())return(-1);
if(_lseeki64(fp,offset,(int)SeekOrigin::Begin)==offset)
return _write(fp,buf,size);
else
return -1;
}
}//namespace io
}//namespace hgl

66
src/Win/LogConsole.cpp Normal file
View File

@ -0,0 +1,66 @@
#include<hgl/Logger.h>
#include<hgl/CodePage.h>
#include<windows.h>
namespace hgl
{
namespace logger
{
constexpr uint LOG_BUF_SIZE=4096;
class LogWinConsole:public Logger
{
private:
DWORD result;
void *console_handle;
u16char buf[LOG_BUF_SIZE];
public:
LogWinConsole(LogLevel ll):Logger(ll)
{
console_handle=GetStdHandle(STD_OUTPUT_HANDLE);
}
bool Create(const UTF16String &)
{
return(true);
}
~LogWinConsole()
{
Close();
}
void Close()
{
CloseHandle(console_handle);
}
void Write(const u16char *str,int size)
{
WriteConsoleW(console_handle,str,size,&result,nullptr);
WriteConsoleW(console_handle,L"\n", 1, &result, nullptr);
}
void Write(const char *str,int size)
{
const int len=u8_to_u16(buf,LOG_BUF_SIZE,str,size);
if(len<=0)return;
buf[len]=L'\n';
WriteConsoleW(console_handle,buf,len+1,&result,nullptr);
}
};//class LogWinConsole
Logger *CreateLoggerConsole(const OSString &,LogLevel ll)
{
return(new LogWinConsole(ll));
}
}//namespace logger
}//namespace hgl

53
src/Win/LogDialog.cpp Normal file
View File

@ -0,0 +1,53 @@
#include<hgl/Logger.h>
#include<hgl/CodePage.h>
#include<windows.h>
namespace hgl
{
namespace logger
{
class LogWinDialog:public Logger
{
UTF16String name;
u16char buf[4096];
public:
LogWinDialog(LogLevel ll):Logger(ll)
{
name=project_code;
}
bool Create(const UTF16String &)
{
return(true);
}
void Close()
{
}
void Write(const u16char *str,int)
{
MessageBoxW(nullptr,str,name,MB_OK);
}
void Write(const char *str,int size)
{
const int len=u8_to_u16(buf,4096,str,size);
if(len<=0)return;
buf[len] = 0;
MessageBoxW(nullptr,buf,name,MB_OK);
}
};//class LogWinDialog
Logger *CreateLoggerDialog(const OSString &,LogLevel ll)
{
return(new LogWinDialog(ll));
}
}//namespace logger
}//namespace hgl

16
src/Win/Pipe.cpp Normal file
View File

@ -0,0 +1,16 @@
#include<hgl/proc/Pipe.h>
namespace hgl
{
bool CreatePipe(pipe_pair &pp)
{
SECURITY_ATTRIBUTES sa;
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle=TRUE;
sa.lpSecurityDescriptor=nullptr;
return CreatePipe(&(pp[0]),&(pp[1]),&sa,0);
}
}//namespace hgl

65
src/Win/ProcMutex.cpp Normal file
View File

@ -0,0 +1,65 @@
#include<hgl/proc/ProcMutex.h>
#include<windows.h>
namespace hgl
{
ProcMutex::ProcMutex()
{
lock = nullptr;
}
bool ProcMutex::Create(const os_char *name)
{
if (lock != nullptr)return(false);
lock = CreateMutexW(NULL, FALSE, name);
if(GetLastError()==ERROR_ALREADY_EXISTS)
{
CloseHandle(lock);
lock=nullptr;
}
return lock;
}
void ProcMutex::Clear()
{
if (lock == nullptr)return;
CloseHandle(lock);
lock = nullptr;
}
bool ProcMutex::Lock()
{
if (lock == nullptr)return(false);
DWORD rv = WaitForSingleObject(lock, INFINITE);
if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED)
return(true);
return(false);
}
bool ProcMutex::TryLock()
{
if (lock == nullptr)return(false);
DWORD rv = WaitForSingleObject(lock, 0);
if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED)
return(true);
return(false);
}
bool ProcMutex::Unlock()
{
if (lock == nullptr)return(false);
return(!ReleaseMutex(lock));
}
}//namespace hgl

49
src/Win/ProgramPath.cpp Normal file
View File

@ -0,0 +1,49 @@
#include<hgl/type/BaseString.h>
#include<windows.h>
#include<shlobj.h>
namespace hgl
{
namespace filesystem
{
void GetLocalAppdataPath(os_char fn[HGL_MAX_PATH])
{
SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, fn);
}
/**
*
*/
bool GetCurrentProgram(OSString &result)
{
os_char *path=new os_char[HGL_MAX_PATH];
GetModuleFileNameW(nullptr,path,HGL_MAX_PATH);
result = path;
delete[] path;
return(true);
}
/**
*
*/
bool GetCurrentProgramPath(OSString &result)
{
os_char *path=new os_char[HGL_MAX_PATH];
int len=GetModuleFileNameW(nullptr,path,HGL_MAX_PATH);
os_char *right=hgl::strrchr(path,len,HGL_DIRECTORY_SEPARATOR);
if(right)
*right=0;
result = path;
delete[] path;
return(true);
}
}//namespace filesystem
}//namespace hgl

25
src/Win/RWLock.cpp Normal file
View File

@ -0,0 +1,25 @@
#include<hgl/thread/RWLock.h>
#pragma warning(disable:4800) // BOOL -> bool 性能损失警告
namespace hgl
{
RWLock::RWLock()
{
lock = new SRWLOCK;
InitializeSRWLock((SRWLOCK *)lock);
}
RWLock::~RWLock()
{
delete (SRWLOCK *)lock;
}
bool RWLock::TryReadLock() { return TryAcquireSRWLockShared((SRWLOCK *)lock); }
bool RWLock::ReadLock() { AcquireSRWLockShared((SRWLOCK *)lock); return(true); }
bool RWLock::ReadUnlock() { ReleaseSRWLockShared((SRWLOCK *)lock); return(true); }
bool RWLock::TryWriteLock() { return TryAcquireSRWLockExclusive((SRWLOCK *)lock); }
bool RWLock::WriteLock() { AcquireSRWLockExclusive((SRWLOCK *)lock); return(true); }
bool RWLock::WriteUnlock() { ReleaseSRWLockExclusive((SRWLOCK *)lock); return(true); }
}//namespace hgl

54
src/Win/Semaphore.cpp Normal file
View File

@ -0,0 +1,54 @@
#include<hgl/thread/Semaphore.h>
#include<hgl/LogInfo.h>
#include<wchar.h>
#pragma warning(disable:4800) // int -> bool 性能损失警告
namespace hgl
{
/**
* @param max_count
*/
Semaphore::Semaphore(int max_count)
{
ptr=CreateSemaphore(nullptr,0,max_count,nullptr);
if(!ptr)
LOG_ERROR(OS_TEXT("CreateSemaphore error,max_count=")+OSString(max_count));
}
Semaphore::~Semaphore()
{
CloseHandle(ptr);
}
/**
*
* @param n
* @return
*/
bool Semaphore::Post(int n)
{
if(n<=0)return(false);
return(ReleaseSemaphore(ptr,n,nullptr));
}
/**
*
* @return
*/
bool Semaphore::TryAcquire()
{
return(WaitForSingleObject(ptr,0)==WAIT_OBJECT_0);
}
/**
*
* @param time ,使0.()
* @return ,,,false
*/
bool Semaphore::Acquire(double time_out)
{
return(WaitForSingleObject(ptr,time_out>0?DWORD(time_out*1000):INFINITE)==WAIT_OBJECT_0);
}
}//namespace hgl

99
src/Win/SystemInfo.cpp Normal file
View File

@ -0,0 +1,99 @@
#include<hgl/platform/SystemInfo.h>
//#include<hgl/platform/ConsoleSystemInitInfo.h>
#include<hgl/LogInfo.h>
#include<hgl/PlugIn.h>
#include<hgl/filesystem/FileSystem.h>
#include<wchar.h>
#include<shlobj.h>
namespace hgl
{
bool GetTempPath(WideString &temp_path,unsigned long s)
{
HKEY hKey;
DWORD type;
LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,L"Environment",0,KEY_READ,&hKey);
if(result==ERROR_SUCCESS)
{
wchar_t temp[HGL_MAX_PATH];
DWORD size=HGL_MAX_PATH;
result = RegQueryValueExW( hKey,L"TEMP", NULL, &type, (LPBYTE)temp, &size );
RegCloseKey(hKey);
if(result==ERROR_SUCCESS)
{
wchar_t path[HGL_MAX_PATH];
ExpandEnvironmentStringsW(temp,path,s);
temp_path=path;
return(true);
}
}
return(false);
}
bool GetCMGDKPath(WideString &cmgdk_path)
{
HKEY hKey;
DWORD type;
LONG result = RegOpenKeyExW(HKEY_CURRENT_USER,L"Environment",0,KEY_READ,&hKey);
if(result==ERROR_SUCCESS)
{
wchar_t path[HGL_MAX_PATH];
DWORD size=HGL_MAX_PATH;
result = RegQueryValueExW( hKey,L"CMGDK", NULL, &type, (LPBYTE)path, &size );
RegCloseKey(hKey);
cmgdk_path=path;
return(result==ERROR_SUCCESS);
}
return(false);
}
void GetOSPath(CMGDKPATH &cp)
{
wchar_t path[HGL_MAX_PATH];
#define GET_FOLDER(str,attrib) SHGetFolderPathW(nullptr,attrib,nullptr,0,path); \
cp.str=path;
GET_FOLDER(os ,CSIDL_WINDOWS );
GET_FOLDER(library ,CSIDL_SYSTEM );
GET_FOLDER(osfont ,CSIDL_FONTS );
hgl::GetTempPath(cp.temp,HGL_MAX_PATH);
GET_FOLDER(common_data ,CSIDL_COMMON_APPDATA );
GET_FOLDER(local_data ,CSIDL_LOCAL_APPDATA );
GET_FOLDER(mydata ,CSIDL_APPDATA );
GET_FOLDER(myprogram ,CSIDL_STARTMENU );
GET_FOLDER(mydesktop ,CSIDL_DESKTOPDIRECTORY );
GET_FOLDER(desktop ,CSIDL_COMMON_DESKTOPDIRECTORY );
#undef GET_FOLDER
}
bool InitOSupport(ConsoleSystemInitInfo *sii)
{
if(sii->CheckDebugger&&IsDebuggerPresent())
{
LOG_ERROR(OS_TEXT("本程序不能运行在调试模式下!"));
return(false);
}
return(true);
}
}//namespace hgl

63
src/Win/Thread.cpp Normal file
View File

@ -0,0 +1,63 @@
#include<hgl/thread/Thread.h>
#include<hgl/LogInfo.h>
namespace hgl
{
extern THREAD_FUNC ThreadFunc(Thread *tc);
/**
* (线)线线tplevel
* @param tplevel 线
* @return 线
*/
bool Thread::Start()
{
unsigned long threadid;
exit_lock.Lock();
tp=::CreateThread(0,0,(PTHREAD_START_ROUTINE)ThreadFunc,this,0,&threadid);
if(!tp)
{
exit_lock.Unlock();
LOG_ERROR(OS_TEXT("Create Thread failed,Windows ErrorCode: ")+OSString((uint)GetLastError()));
return(false);
}
return(true);
}
/**
* 线
*/
bool Thread::IsCurThread()
{
return(tp==GetCurrentThread());
}
void WaitThreadExit(thread_ptr tp,const double &time_out)
{
if(!tp)return;
WaitForSingleObject(tp,time_out>0?time_out*1000:INFINITE);
}
/**
* 线
* @param mt 线
* @param count 线
* @param time_out 0线0
*/
void WaitThread(Thread **mt,int count,double time_out)
{
void **obj=new void *[count];
for(int i=0;i<count;i++)
obj[i]=mt[i]->tp;
WaitForMultipleObjects(count,obj,false,time_out>0?time_out*1000:INFINITE);
delete[] obj;
}
}//namespace hgl

55
src/Win/ThreadMutex.cpp Normal file
View File

@ -0,0 +1,55 @@
#include<hgl/thread/ThreadMutex.h>
#include<wchar.h>
#pragma warning(disable:4800) // BOOL -> bool 性能损失警告
namespace hgl
{
ThreadMutex::ThreadMutex()
{
InitializeCriticalSection(&ptr);
}
ThreadMutex::~ThreadMutex()
{
Unlock();
DeleteCriticalSection(&ptr);
}
/**
*
*
*/
void ThreadMutex::Lock()
{
EnterCriticalSection(&ptr);
}
/**
*
* @return
*/
bool ThreadMutex::TryLock()
{
return(TryEnterCriticalSection(&ptr));
}
/**
*
* @param time ,0
* @return
*/
bool ThreadMutex::WaitLock(double time_out)
{
return(!WaitForSingleObject(&ptr,time_out*1000));
}
/**
*
*/
void ThreadMutex::Unlock()
{
LeaveCriticalSection(&ptr);
}
}//namespace hgl

90
src/Win/Time.cpp Normal file
View File

@ -0,0 +1,90 @@
#include<hgl/platform/Platform.h>
#include<hgl/TypeFunc.h>
namespace hgl
{
namespace
{
#define APR_DELTA_EPOCH_IN_USEC 11644473600000000 //转Windows时间到Unix时间的一个差值
//Windows是1601.1.1
//Unix是1970.1.1
//tanks for APR
static inline void FileTimeToMicroTime(uint64 *result, FILETIME *input)
{
/* Convert FILETIME one 64 bit number so we can work with it. */
*result = input->dwHighDateTime;
*result = (*result) << 32;
*result |= input->dwLowDateTime;
*result /= 10; /* Convert from 100 nano-sec periods to micro-seconds. */
*result -= APR_DELTA_EPOCH_IN_USEC; /* Convert from Windows epoch to Unix epoch */
return;
}
}//namespace
long GetGMTOff()
{
SYSTEMTIME st;
FILETIME ft;
uint64 local_time;
uint64 utc_time;
GetLocalTime(&st);
SystemTimeToFileTime(&st, &ft);
FileTimeToMicroTime(&local_time, &ft);
GetSystemTime(&st);
SystemTimeToFileTime(&st, &ft);
FileTimeToMicroTime(&utc_time, &ft);
return(utc_time - local_time);
}
/**
*
* @return ()
*/
uint64 GetMicroTime()
{
SYSTEMTIME st;
FILETIME ft;
uint64 result;
GetLocalTime(&st);
SystemTimeToFileTime(&st, &ft);
FileTimeToMicroTime(&result, &ft);
return(result);
}
/**
*
* @return ()
*/
uint64 GetTime()
{
return(GetMicroTime() / 1000);
}
/**
* ()
* @return ()
*/
double GetDoubleTime() ///<取得当前时间(双精度,单位秒)
{
return(double(GetMicroTime()) / HGL_MICRO_SEC_PER_SEC);
}
/**
*
* @param time ()
*/
void WaitTime(double t)
{
if(t<=0)return;
::Sleep(DWORD(t*HGL_MILLI_SEC_PRE_SEC));
}
}//namespace hgl

328
src/Win/WinMessage.cpp Normal file
View File

@ -0,0 +1,328 @@
#include"WinWindow.h"
#include<hgl/platform/InputDevice.h>
#include<Windows.h>
#ifdef _DEBUG
#include<hgl/LogInfo.h>
#endif//_DEBUG
namespace hgl
{
namespace
{
static KeyboardButton KeyConvert[256];
static void (*WMProc[2048])(WinWindow *,uint32,uint32); //消息处理队列
uint32 GetMouseKeyFlags(uint32 wflags)
{
uint32 flag=0;
if(wflags&MK_LBUTTON)flag|=mbLeft;
if(wflags&MK_RBUTTON)flag|=mbRight;
if(wflags&MK_MBUTTON)flag|=mbMid;
if(wflags&MK_XBUTTON1)flag|=mbX1;
if(wflags&MK_XBUTTON2)flag|=mbX2;
if(wflags&MK_SHIFT )flag|=mbShift;
if(wflags&MK_CONTROL)flag|=mbCtrl;
return(flag);
}
void InitKeyConvert()
{
int i;
memset(KeyConvert,0,sizeof(KeyConvert));
KeyConvert[VK_ESCAPE ]=kbEsc;
for(i=VK_F1;i<=VK_F12;i++)KeyConvert[i]=(KeyboardButton)(kbF1+i-VK_F1);
KeyConvert['`' ]=kbGrave;
for(i='0';i<='9';i++)KeyConvert[i]=(KeyboardButton)(kb0+i-'0');
KeyConvert['-' ]=kbMinus;
KeyConvert['=' ]=kbEquals;
KeyConvert['\\' ]=kbBackSlash;
KeyConvert[VK_BACK ]=kbBackSpace;
KeyConvert[VK_TAB ]=kbTab;
KeyConvert['Q' ]=kbQ;
KeyConvert['W' ]=kbW;
KeyConvert['E' ]=kbE;
KeyConvert['R' ]=kbR;
KeyConvert['T' ]=kbT;
KeyConvert['Y' ]=kbY;
KeyConvert['U' ]=kbU;
KeyConvert['I' ]=kbI;
KeyConvert['O' ]=kbO;
KeyConvert['P' ]=kbP;
KeyConvert['[' ]=kbLeftBracket;
KeyConvert[']' ]=kbRightBracket;
KeyConvert[VK_CAPITAL ]=kbCapsLock;
KeyConvert['A' ]=kbA;
KeyConvert['S' ]=kbS;
KeyConvert['D' ]=kbD;
KeyConvert['F' ]=kbF;
KeyConvert['G' ]=kbG;
KeyConvert['H' ]=kbH;
KeyConvert['J' ]=kbJ;
KeyConvert['K' ]=kbK;
KeyConvert['L' ]=kbL;
KeyConvert[';' ]=kbSemicolon;
KeyConvert['\'' ]=kbApostrophe;
KeyConvert[VK_RETURN ]=kbEnter;
KeyConvert[VK_LSHIFT ]=kbLeftShift;
KeyConvert['Z' ]=kbZ;
KeyConvert['X' ]=kbX;
KeyConvert['C' ]=kbC;
KeyConvert['V' ]=kbV;
KeyConvert['B' ]=kbB;
KeyConvert['N' ]=kbN;
KeyConvert['M' ]=kbM;
KeyConvert[',' ]=kbComma;
KeyConvert['.' ]=kbPeriod;
KeyConvert['/' ]=kbSlash;
KeyConvert[VK_RSHIFT ]=kbRightShift;
KeyConvert[VK_LCONTROL ]=kbLeftCtrl;
KeyConvert[VK_LWIN ]=kbLeftOS;
KeyConvert[VK_LMENU ]=kbLeftAlt;
KeyConvert[VK_SPACE ]=kbSpace;
KeyConvert[VK_RMENU ]=kbRightAlt;
KeyConvert[VK_RWIN ]=kbRightOS;
KeyConvert[VK_RCONTROL ]=kbRightCtrl;
KeyConvert[VK_PAUSE ]=kbPause;
// KeyConvert[VK_CLEAR ]=kbClear;
KeyConvert[VK_NUMPAD0 ]=kbNum0;
KeyConvert[VK_NUMPAD1 ]=kbNum1;
KeyConvert[VK_NUMPAD2 ]=kbNum2;
KeyConvert[VK_NUMPAD3 ]=kbNum3;
KeyConvert[VK_NUMPAD4 ]=kbNum4;
KeyConvert[VK_NUMPAD5 ]=kbNum5;
KeyConvert[VK_NUMPAD6 ]=kbNum6;
KeyConvert[VK_NUMPAD7 ]=kbNum7;
KeyConvert[VK_NUMPAD8 ]=kbNum8;
KeyConvert[VK_NUMPAD9 ]=kbNum9;
KeyConvert[VK_DECIMAL ]=kbNumDecimal;
KeyConvert[VK_DIVIDE ]=kbNumDivide;
KeyConvert[VK_MULTIPLY ]=kbNumMultiply;
KeyConvert[VK_SUBTRACT ]=kbNumSubtract;
KeyConvert[VK_ADD ]=kbNumAdd;
KeyConvert[VK_UP ]=kbUp;
KeyConvert[VK_DOWN ]=kbDown;
KeyConvert[VK_LEFT ]=kbLeft;
KeyConvert[VK_RIGHT ]=kbRight;
KeyConvert[VK_INSERT ]=kbInsert;
KeyConvert[VK_DELETE ]=kbDelete;
KeyConvert[VK_HOME ]=kbHome;
KeyConvert[VK_END ]=kbEnd;
KeyConvert[VK_PRIOR ]=kbPageUp;
KeyConvert[VK_NEXT ]=kbPageDown;
KeyConvert[VK_NUMLOCK ]=kbNumLock;
KeyConvert[VK_SCROLL ]=kbScrollLock;
//KeyConvert[VK_SHIFT ]=kbLeftShift;
//KeyConvert[VK_CONTROL ]=kbLeftCtrl;
//KeyConvert[VK_MENU ]=kbLeftAlt;
KeyConvert[VK_OEM_1 ]=kbSemicolon;
KeyConvert[VK_OEM_PLUS ]=kbEquals;
KeyConvert[VK_OEM_COMMA ]=kbComma;
KeyConvert[VK_OEM_MINUS ]=kbMinus;
KeyConvert[VK_OEM_PERIOD]=kbPeriod;
KeyConvert[VK_OEM_2 ]=kbSlash;
KeyConvert[VK_OEM_3 ]=kbGrave;
KeyConvert[VK_OEM_4 ]=kbLeftBracket;
KeyConvert[VK_OEM_5 ]=kbBackSlash;
KeyConvert[VK_OEM_6 ]=kbRightBracket;
KeyConvert[VK_OEM_7 ]=kbApostrophe;
}
KeyboardButton ConvertOSKey(uint key)
{
if(key>=256)return(kbBeginRange);
if(KeyConvert[key]==0)return(kbBeginRange);
if(key==VK_SHIFT)
{
if((GetAsyncKeyState(VK_LSHIFT)>>15)&1)
return kbLeftShift;
else
return kbRightShift;
}
else
if(key==VK_CONTROL)
{
if((GetAsyncKeyState(VK_LCONTROL)>>15)&1)
return kbLeftCtrl;
else
return kbRightCtrl;
}
if(key==VK_MENU)
{
if((GetAsyncKeyState(VK_LMENU)>>15)&1)
return kbLeftAlt;
else
return kbRightAlt;
}
#ifdef _DEBUG
if(KeyConvert[key]==0)
{
wchar_t name[64];
::GetKeyNameTextW(key,name,64);
LOG_INFO(WideString(L"Unknow Key: " )+WideString(key)
+WideString(L" ,name: " )+WideString(name));
}
#endif _DEBUG
return KeyConvert[key];
}
void WMProcDestroy(WinWindow *win,uint32,uint32)
{
win->ProcClose();
PostQuitMessage(0);
}
#define WMEF_MOUSE(button,action) void WMProcMouse##button##action(WinWindow *win,uint32 wParam,uint32 lParam) \
{ \
const int x=LOWORD(lParam); \
const int y=HIWORD(lParam); \
\
win->ProcMouseMove(x,y); \
win->ProcMouse##action(x,y,mb##button|GetMouseKeyFlags(wParam)); \
}
WMEF_MOUSE(Left,Down);
WMEF_MOUSE(Left,Up);
WMEF_MOUSE(Left,DblClick);
WMEF_MOUSE(Mid,Down);
WMEF_MOUSE(Mid,Up);
WMEF_MOUSE(Mid,DblClick);
WMEF_MOUSE(Right,Down);
WMEF_MOUSE(Right,Up);
WMEF_MOUSE(Right,DblClick);
void WMProcMouseMove(WinWindow *win,uint32 wParam,uint32 lParam)
{
win->ProcMouseMove(LOWORD(lParam),HIWORD(lParam));
}
#undef WMEF_MOUSE
#define WMEF2(name) void name(WinWindow *win,uint32 wParam,uint32 lParam)
WMEF2(WMProcMouseWheel)
{
int zDelta=GET_WHEEL_DELTA_WPARAM(wParam);
uint key=ConvertOSKey(GET_KEYSTATE_WPARAM(wParam));
win->ProcMouseWheel(zDelta,0,key);
}
WMEF2(WMProcMouseHWheel)
{
int zDelta=GET_WHEEL_DELTA_WPARAM(wParam);
uint key=ConvertOSKey(GET_KEYSTATE_WPARAM(wParam));
win->ProcMouseWheel(0,zDelta,key);
}
WMEF2(WMProcSize)
{
win->ProcResize(LOWORD(lParam),HIWORD(lParam));
}
#undef WMEF2
#define WMEF1(name) void name(WinWindow *win,uint32 wParam,uint32)
WMEF1(WMProcKeyDown)
{
win->ProcKeyDown(ConvertOSKey(wParam));
}
WMEF1(WMProcKeyUp)
{
win->ProcKeyUp(ConvertOSKey(wParam));
}
WMEF1(WMProcChar)
{
win->ProcChar((wchar_t)wParam);
}
WMEF1(WMProcActive)
{
//if(JoyPlugIn)
// JoyInterface.SetInputActive(wParam);
win->ProcActive(wParam);
}
#undef WMEF1
}//namespace
void InitMessageProc()
{
memset(WMProc,0,sizeof(WMProc));
InitKeyConvert();
//if(joy)
// LoadJoystick(win->hInstance,win->hWnd);
#define WM_MAP(wm,func) WMProc[wm]=func;
WM_MAP(WM_CLOSE ,WMProcDestroy);
WM_MAP(WM_LBUTTONDOWN ,WMProcMouseLeftDown);
WM_MAP(WM_LBUTTONUP ,WMProcMouseLeftUp);
WM_MAP(WM_LBUTTONDBLCLK ,WMProcMouseLeftDblClick);
WM_MAP(WM_MBUTTONDOWN ,WMProcMouseMidDown);
WM_MAP(WM_MBUTTONUP ,WMProcMouseMidUp);
WM_MAP(WM_MBUTTONDBLCLK ,WMProcMouseMidDblClick);
WM_MAP(WM_RBUTTONDOWN ,WMProcMouseRightDown);
WM_MAP(WM_RBUTTONUP ,WMProcMouseRightUp);
WM_MAP(WM_RBUTTONDBLCLK ,WMProcMouseRightDblClick);
WM_MAP(WM_MOUSEWHEEL ,WMProcMouseWheel);
WM_MAP(WM_MOUSEHWHEEL ,WMProcMouseHWheel);
WM_MAP(WM_MOUSEMOVE ,WMProcMouseMove);
WM_MAP(WM_KEYDOWN ,WMProcKeyDown);
WM_MAP(WM_KEYUP ,WMProcKeyUp);
WM_MAP(WM_SYSKEYDOWN ,WMProcKeyDown);
WM_MAP(WM_SYSKEYUP ,WMProcKeyUp);
WM_MAP(WM_CHAR ,WMProcChar);
WM_MAP(WM_SYSCHAR ,WMProcChar);
WM_MAP(WM_ACTIVATE ,WMProcActive);
WM_MAP(WM_SIZE ,WMProcSize);
#undef WM_MAP
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if(uMsg<2048)
if(WMProc[uMsg])
{
WinWindow *win=(WinWindow *)GetWindowLongPtrW(hWnd,GWLP_USERDATA);
if(win)
WMProc[uMsg](win,wParam,lParam);
}
return (DefWindowProcW(hWnd, uMsg, wParam, lParam));
}
void InitNativeWindowSystem()
{
InitMessageProc();
}
}//namespace hgl

30
src/Win/WinVulkan.cpp Normal file
View File

@ -0,0 +1,30 @@
#include<hgl/platform/Vulkan.h>
#include"WinWindow.h"
#include<vulkan/vulkan_win32.h>
namespace hgl
{
VkSurfaceKHR CreateVulkanSurface(VkInstance vk_inst,Window *w)
{
if(vk_inst==VK_NULL_HANDLE)return(VK_NULL_HANDLE);
if(!w)return(VK_NULL_HANDLE);
WinWindow *win=(WinWindow *)w;
VkWin32SurfaceCreateInfoKHR createInfo;
createInfo.sType =VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
createInfo.pNext =nullptr;
createInfo.flags =0;
createInfo.hinstance=win->GetInstance();
createInfo.hwnd =win->GetWnd();
VkSurfaceKHR surface;
VkResult res=vkCreateWin32SurfaceKHR(vk_inst,&createInfo,nullptr,&surface);
if(res!=VK_SUCCESS)
return(VK_NULL_HANDLE);
return(surface);
}
}//namespace hgl

213
src/Win/WinWindow.cpp Normal file
View File

@ -0,0 +1,213 @@
#include"WinWindow.h"
namespace hgl
{
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
namespace
{
constexpr wchar_t WIN_CLASS_NAME[] = L"CMGameEngine/ULRE Window Class";
bool RegistryWinClass(HINSTANCE hInstance)
{
WNDCLASSEXW win_class;
hgl_zero(win_class);
win_class.cbSize = sizeof(WNDCLASSEXW);
win_class.style = CS_HREDRAW | CS_VREDRAW;
win_class.lpfnWndProc = WindowProc;
win_class.cbClsExtra = 0;
win_class.cbWndExtra = 0;
win_class.hInstance = hInstance;
win_class.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
win_class.hCursor = LoadCursor(nullptr, IDC_ARROW);
win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
win_class.lpszMenuName = nullptr;
win_class.lpszClassName = WIN_CLASS_NAME;
win_class.hIconSm = LoadIcon(nullptr, IDI_WINLOGO);
return RegisterClassExW(&win_class);
}
}//namespace
bool WinWindow::Create()
{
constexpr DWORD win_style = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU ;
int win_left, win_top;
int win_width, win_height;
{
RECT win_rect;
win_rect.left = 0;
win_rect.right = width;
win_rect.top = 0;
win_rect.bottom = height;
AdjustWindowRectEx(&win_rect, win_style, false, 0); //计算窗口坐标
win_width = win_rect.right - win_rect.left;
win_height = win_rect.bottom - win_rect.top;
}
if (width && height)
{
win_left = (GetSystemMetrics(SM_CXSCREEN) - win_width) / 2;
win_top = (GetSystemMetrics(SM_CYSCREEN) - win_height) / 2;
}
else
{
win_left = CW_USEDEFAULT;
win_top = CW_USEDEFAULT;
}
win_hwnd = CreateWindowExW(0,
WIN_CLASS_NAME, // class name
win_name.c_str(), // app name
win_style, // window style
win_left,win_top, // x/y coords
win_width, // width
win_height, // height
nullptr, // handle to parent
nullptr, // handle to menu
hInstance, // hInstance
nullptr); // no extra parameters
if (!win_hwnd)
{
UnregisterClassW(WIN_CLASS_NAME, hInstance);
return(false);
}
win_dc = GetDC(win_hwnd);
SetWindowLongPtrW(win_hwnd, GWLP_USERDATA, (LONG_PTR)this);
return(true);
}
WinWindow::~WinWindow()
{
Close();
}
bool WinWindow::Create(uint w, uint h)
{
full_screen=false;
width = w;
height = h;
hInstance = GetModuleHandleW(nullptr);
if (!RegistryWinClass(hInstance))
return(false);
if(!Create())
{
is_close=true;
return(false);
}
else
{
is_close=false;
return(true);
}
}
bool WinWindow::Create(uint, uint, uint)
{
full_screen=true;
return(false);
}
void WinWindow::Close()
{
if(win_hwnd)
{
if(win_dc)
{
ReleaseDC(win_hwnd,win_dc);
win_dc = nullptr;
}
DestroyWindow(win_hwnd);
win_hwnd = nullptr;
}
UnregisterClassW(WIN_CLASS_NAME,hInstance);
is_close = true;
}
void WinWindow::SetCaption(const OSString &caption)
{
win_name=caption;
SetWindowTextW(win_hwnd,caption.c_str());
}
void WinWindow::Show()
{
ShowWindow(win_hwnd, SW_SHOW);
SetForegroundWindow(win_hwnd);
SetFocus(win_hwnd);
UpdateWindow(win_hwnd);
}
void WinWindow::Hide()
{
ShowWindow(win_hwnd, SW_HIDE);
UpdateWindow(win_hwnd);
}
void WinWindow::ToMinWindow()
{
if(!full_screen)
ShowWindow(win_hwnd,SW_MINIMIZE);
}
void WinWindow::ToMaxWindow()
{
if(!full_screen)
ShowWindow(win_hwnd,SW_MAXIMIZE);
}
void WinWindow::SetSystemCursor(bool visible)
{
::ShowCursor(visible);
}
bool WinWindow::MessageProc()
{
if(PeekMessage(&win_msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&win_msg);
DispatchMessage(&win_msg);
if(win_msg.message==WM_QUIT)
ProcClose();
return(true);
}
else
{
//if(JoyPlugIn)
//{
// JoyInterface.Update();
//}
return(false);
}
}
bool WinWindow::WaitMessage()
{
return ::WaitMessage();
}
Window *CreateRenderWindow(const WideString& win_name)
{
return(new WinWindow(win_name));
}
}//namespace hgl

47
src/Win/WinWindow.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#include<hgl/platform/Window.h>
#include<Windows.h>
namespace hgl
{
/**
* Windows平台窗口实现
*/
class WinWindow:public Window
{
HINSTANCE hInstance = nullptr;
HWND win_hwnd = nullptr;
HDC win_dc = nullptr;
MSG win_msg;
protected:
bool Create();
public:
using Window::Window;
~WinWindow();
bool Create(uint w, uint h) override;
bool Create(uint, uint, uint) override;
void Close() override;
HINSTANCE GetInstance(){return hInstance;}
HWND GetWnd(){return win_hwnd;}
HDC GetHDC(){return win_dc;}
void SetCaption(const OSString &caption) override;
void Show() override;
void Hide() override;
void ToMinWindow() override;
void ToMaxWindow() override;
void SetSystemCursor(bool visible) override;
bool MessageProc() override;
bool WaitMessage() override;
};//class WinWindow :public Window
}//namespace win

66
src/Window.cpp Normal file
View File

@ -0,0 +1,66 @@
#include<hgl/platform/Window.h>
namespace hgl
{
void Window::ProcKeyDown(KeyboardButton kb)
{
if(key_push[kb])
ProcKeyPress(kb);
else
key_push[kb]=true;
SafeCallEvent(OnKeyDown,(kb));
}
void Window::ProcKeyUp(KeyboardButton kb)
{
key_push[kb]=false;
SafeCallEvent(OnKeyUp,(kb));
}
void Window::ProcResize(uint w,uint h)
{
if(w==width&&height==h)
return;
width=w;
height=h;
if(w==0||h==0)
{
is_min=true;
}
else
{
is_min=false;
}
SafeCallEvent(OnResize,(w,h));
}
void Window::ProcActive(bool a)
{
active=a;
SafeCallEvent(OnActive,(a));
}
void Window::ProcClose()
{
is_close=true;
SafeCallEvent(OnClose,());
}
bool Window::Update()
{
while(MessageProc());
if(is_close)
return(false);
if(!active||is_min)
this->WaitMessage();
return(true);
}
}//namespace hgl