亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

linux系統中c++寫日志文件功能分享

2020-01-26 15:35:14
字體:
來源:轉載
供稿:網友

簡化了glog,只保留了寫日志文件的功能,只是改寫了linux版本,win版本未改寫,可以用
LOG(INFO)<< 輸出日志
也可用LOG_IF(INFO,condition)<<輸出日志
也可直接調用日志類Logger::GetInstance().Error 等方式寫日志
初始化時調用 InitLogging(argv[0],INFO,"./log/test");
第一個參數是路徑,第二個參數是最低日志級別,第三個參數表示日志文件的前綴和文件夾

FileHelper.h
#ifndef FILEHELPER_H_
#define FILEHELPER_H_
#include <string>
#include <vector>
#include <fstream>
#include <stdio.h>
#ifdef _WIN32
#include <direct.h>
#include <io.h>
#else
#include <stdarg.h>
#include <sys/stat.h>
#endif

namespace FrameWork {
#ifdef _WIN32
#define ACCESS _access
#define MKDIR(a) _mkdir((a))
#else
#define ACCESS access
#define MKDIR(a) mkdir((a),0755)
#endif

class FileHelper {
public:
 static bool save(const std::string filename, std::string& content)
 {
        FILE *file = fopen(filename.c_str(), "wb");

        if (file == NULL)
            return false;
  fwrite(content.c_str(),sizeof(char),content.size(),file);
  fclose(file);
  return true;
 }

    // used to open binary file
    static bool open(const std::string filename, std::string& content)
    {
        FILE *file = fopen(filename.c_str(), "rb");

        if (file == NULL)
            return false;

        fseek(file, 0, SEEK_END);
        int len = ftell(file);
  rewind(file);
  content.clear();
        char *buffer = new char[len];
        fread(buffer, sizeof(char), len, file);
        content.assign(buffer, len);
        delete []buffer;

  //int nRead;
  //content.clear();
  //char buffer[80];
  //while(!feof(file)){
  // nRead = fread(buffer,sizeof(char),sizeof(buffer),file);
  // if(nRead > 0){
  //  content.append(buffer);
  // }
  //}
        fclose(file);
        return true;
    }

    // used to open text file
    static bool open(const std::string file_name, std::vector<std::string>& lines)
    {
        std::ifstream file(file_name.c_str(), std::ios::in);
        if (!file)
        {
            return false;
        }

        lines.clear();
        char buffer[BUFFER_SIZE];

        while (file.getline(buffer, BUFFER_SIZE, '/n'))
        {
            lines.push_back(buffer);
        }

        return true;
    }
    static bool CreateDir(const char *pszDir)
    {
     size_t i = 0;
     size_t iRet;
     size_t iLen = strlen(pszDir);
     char* buf=new char[iLen+1];
     strncpy(buf,pszDir,iLen+1);
     for (i = 0;i < iLen;i ++) {
      if (pszDir[i] == '//' || pszDir[i] == '/') {
       buf[i] = '/0';
       //如果不存在,創建
       iRet = ACCESS(buf,0);
       if (iRet != 0) {
        iRet = MKDIR(buf);
        if (iRet != 0) {
         delete[] buf;
         return false;
        }
       }
       //支持linux,將所有/換成/
       buf[i] = '/';
      }
     }
     delete[] buf;
     return true;
    }


private:

    enum { BUFFER_SIZE = 3000 };

};

} /* namespace FrameWork */
#endif /* FILEHELPER_H_ */
[/code]

Logger.cpp

復制代碼 代碼如下:

#include "Logger.h"
#include<cstring>
#include<time.h>
#include<cstdarg>
#include<cstdlib>
#include<assert.h>
#include "FileHelper.h"
#include "Mutex.h"
namespace FrameWork {
Mutex LogMessage::mutex;
static char _defaltFolder[]="/var/tmp/";
static char _appName[MaxFilePathLen];
static char _appFolder[MaxFilePathLen];
static char _destFolder[MaxFilePathLen];
static char _destPrefix[MaxFilePathLen];
static LogLevel _destLevel;
static char _levelInfos[][16]={
 "Debug","Info","Warn","Error","Fatal"
};
const int BUFFER_SIZE = 8196;
static char _gBuffer[BUFFER_SIZE];
void combine_folder(char** destpath, char* basefolder,char* relativefolder)
{
 int lenb = strlen(basefolder);
 int lenr = strlen(relativefolder);
 char* pret = (char*)malloc((lenb+lenr+1)*sizeof(char));
 int pos=lenb-1;
 memset(pret,0,lenb+lenr+1);
 while(pos>0 && ( basefolder[pos]!='/'))
  pos--;
 strncpy(*destpath,basefolder,pos+1);
 if(relativefolder[0] == '//' || relativefolder[0] == '/'){
  strncpy(*destpath+pos+1,relativefolder+1,lenr-1);
 }else{
  strncpy(*destpath+pos+1,relativefolder,lenr);
 }
}

static void InitPaths(const char* filename,const char* destFolder)
{
 memset(_appName,0,MaxFilePathLen);
 memset(_appFolder,0,MaxFilePathLen);
 memset(_destFolder,0,MaxFilePathLen);
 memset(_destPrefix,0,MaxFilePathLen);

 strcpy(_appName,filename);
 int len = strlen(filename),lend;
 int pos = len-1,posd,start;
 while(pos >0 && filename[pos] != PathSplitChar)
  pos--;
 strncpy(_appFolder,filename,pos+1);
 lend = strlen(destFolder);
 posd = lend-1;
 if(destFolder[lend-1] != PathSplitChar) {
  //has prefix
  while(posd >0 && destFolder[posd] != PathSplitChar)
   posd--;
 }
 if(destFolder[0] == '.' && destFolder[1] == PathSplitChar){
  strncpy(_destFolder,filename,pos+1);
  start = 2;
 } else{
  pos = 8;
  strcpy(_destFolder,_defaltFolder);
  if(destFolder[0] != PathSplitChar){
   start = 0;
  }else{
   start = 1;
  }
 }
 strncpy(_destFolder+pos+1,destFolder+start,posd-start+1);
 strncpy(_destPrefix,filename,pos+1);
 strncpy(_destPrefix+pos+1,destFolder+start,lend-start);
}

void InitLogging(const char* filename,LogLevel minlevel,const char* destFolder)
{
 InitPaths(filename,destFolder);
 _destLevel = minlevel;
}

 

static string GetLocalDate(void)
{
 time_t t = time(0);
 tm *ld;
 char tmp[64] = "";
 ld=localtime(&t);
 strftime(tmp,sizeof(tmp),"%Y-%m-%d",ld);
 return string(tmp);
}
static string GetCurTime(void)
{
 time_t t = time(0);
 tm *ld;
 char tmp[64] = "";
 ld=localtime(&t);
 strftime(tmp,sizeof(tmp),"%Y-%m-%d %H:%M:%S",ld);
 return string(tmp);
}

Logger::Logger(LogLevel level,char * folder,char * prefix)
 :level(level)
{
 std::string path;
 path.append(prefix);
 path.append(GetLocalDate());
 path.append(".log");
 FileHelper::CreateDir(folder);
 logPrefix.append(prefix);
 logPath = path;
 logFile.open(path.c_str(),ios::app|ios::out);
 logFile<<"Log file created at:"<<GetCurTime()<<endl;
}

Logger::~Logger() {
 logFile.close();
}

#define IMPLEMENT_LOG_FUNC1(cname,fname,lv) /
void cname::fname(string msg) {/
    if(level <= lv){/
        WriterMutexLock lock(&mutex);/
        logFile<<"["<<GetCurTime().c_str()<<"][" #lv "]"<<msg.c_str()<<endl;/
        logFile.flush();/
    }/
}

#define PRINT_ARGS_TO_BUFFER(fmt,buf) /
    {/
        memset(buf,0,sizeof(buf));/
  va_list argp;/
  va_start(argp,fmt);/
  vsprintf(buf,fmt,argp);/
  va_end(argp);/
    }

#define IMPLEMENT_LOG_FUNC2(cname,fname,lv) /
void cname::fname(const char* format,...) {/
 if(level <= lv){/
  WriterMutexLock lock(&mutex);/
  PRINT_ARGS_TO_BUFFER(format,_gBuffer)/
  logFile<<"["<<GetCurTime().c_str()<<"][" #lv "]"<<_gBuffer<<endl;/
  logFile.flush();/
 }/
}


#define IMPLEMENT_LOG_FUNC(cname,fname,lv) /
IMPLEMENT_LOG_FUNC1(cname,fname,lv)/
IMPLEMENT_LOG_FUNC2(cname,fname,lv)

IMPLEMENT_LOG_FUNC(Logger,Debug,DEBUG)
IMPLEMENT_LOG_FUNC(Logger,Info,INFO)
IMPLEMENT_LOG_FUNC(Logger,Warn,WARN)
IMPLEMENT_LOG_FUNC(Logger,Error,ERROR)
IMPLEMENT_LOG_FUNC(Logger,Fatal,FATAL)

Logger& Logger::GetInstance() {
 static Logger _logger(_destLevel,_destFolder,_destPrefix);
 return _logger;
}

void Logger::Log(LogLevel lv, string msg) {
 if(level <= lv){
  WriterMutexLock lock(&mutex);
  logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]"<<msg.c_str()<<endl;
  logFile.flush();
 }
}

void Logger::Log(LogLevel lv, const char* format,...) {
 if(level <= lv){
  WriterMutexLock lock(&mutex);
  PRINT_ARGS_TO_BUFFER(format,_gBuffer)
  logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]"<<_gBuffer<<endl;
  logFile.flush();
 }
}

void Logger::Log(const char* file, int line, LogLevel lv, string msg) {
 if(level <= lv){
  WriterMutexLock lock(&mutex);
  logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]["<<file<<"]["<<line<<"]"<<msg.c_str();
  logFile.flush();
 }
}

Logger* Logger::GetInstancePtr() {
 return &GetInstance();
}

void Logger::Log(const char* file, int line, LogLevel lv, const char* format,...) {
 if(level <= lv){
  WriterMutexLock lock(&mutex);
  PRINT_ARGS_TO_BUFFER(format,_gBuffer)
  logFile<<"["<<GetCurTime().c_str()<<"]["<<_levelInfos[lv+1]<<"]["<<file<<"]["<<line<<"]"<<_gBuffer;
  logFile.flush();
 }
}

LogMessage::LogMessage(const char* file, int line, LogLevel lv) {
 logger = Logger::GetInstancePtr();
 mutex.Lock();
 logger->Log(file,line,lv,"");
}

LogMessage::~LogMessage() {
 logger->stream()<<endl;
 logger->stream().flush();
 mutex.Unlock();
}

} /* namespace FrameWork */

Logger.h

復制代碼 代碼如下:

#ifndef LOGGER_H_
#define LOGGER_H_

#include "ILogger.h"
#include "Mutex.h"
#include<fstream>
#include<string>
const int MaxFilePathLen = 1024;
const char PathSplitChar = '/';
namespace FrameWork {
enum LogLevel{
    /// <summary>
    /// 調試
    /// </summary>
    DEBUG = -1,
    /// <summary>
    /// 普通日志
    /// </summary>
    INFO = 0,
    /// <summary>
    /// 警告
    /// </summary>
    WARN,
    /// <summary>
    /// 錯誤
    /// </summary>
    ERROR,
    /// <summary>
    /// 崩潰
    /// </summary>
    FATAL,
    /// <summary>
    /// 超出錯誤級別
    /// </summary>
    OFF
};


class ILogger {
public:
 //
 virtual ~ILogger(){}
#define ABSTRACT_LOG_FUNC(name) /
    virtual void name(string msg)=0; /
    virtual void name(const char* fmt,...)=0;

    ABSTRACT_LOG_FUNC(Debug)
    ABSTRACT_LOG_FUNC(Info)
    ABSTRACT_LOG_FUNC(Warn)
    ABSTRACT_LOG_FUNC(Error)
    ABSTRACT_LOG_FUNC(Fatal)

#undef ABSTRACT_LOG_FUNC
#define ABSTRACT_LOG_FUNC_X(name) /
    virtual void name(LogLevel lv,string msg)=0; /
    virtual void name(LogLevel lv,const char* fmt,...)=0;/
    virtual void name(const char* file,int line,LogLevel lv,string msg)=0;/
    virtual void name(const char* file,int line,LogLevel lv,const char* fmt,...)=0;
    ABSTRACT_LOG_FUNC_X(Log)

#undef LOG_FUNC_X
};


class Logger: public ILogger {
 std::string logPath;
 std::string logPrefix;
 std::fstream logFile;
 LogLevel level;
 Mutex mutex;

 Logger(LogLevel level,char * folder,char * prefix);

public:
 static Logger& GetInstance();
 static Logger* GetInstancePtr();
 virtual ~Logger();
 inline fstream & stream(){return logFile;}

#define DECLARE_LOG_FUNC(name) /
    virtual void name(string msg); /
    virtual void name(const char* fmt,...);

#define DECLARE_LOG_FUNC_X(name) /
    virtual void name(LogLevel lv,string msg); /
    virtual void name(LogLevel lv,const char* fmt,...);/
    virtual void name(const char* file,int line,LogLevel lv,string msg);/
    virtual void name(const char* file,int line,LogLevel lv,const char* fmt,...);

    DECLARE_LOG_FUNC(Debug)
    DECLARE_LOG_FUNC(Info)
    DECLARE_LOG_FUNC(Warn)
    DECLARE_LOG_FUNC(Error)
    DECLARE_LOG_FUNC(Fatal)

    DECLARE_LOG_FUNC_X(Log)

#undef DECLARE_LOG_FUNC_X
#undef DECLARE_LOG_FUNC

};

class LogMessage {
 Logger* logger;
 static Mutex mutex;
public:
 LogMessage(const char* file, int line,LogLevel lv);
 ostream& stream(){return logger->stream();}
 virtual ~LogMessage();
};


void InitLogging(const char* filename,LogLevel minlevel,const char* destFolder);
void CloseLogging();

#define LOG(level) LogMessage(__FILE__, __LINE__,level).stream()
#define LOG_IF(severity, condition) /
 !(condition) ? (void) 0 : LOG(severity)
#define LOG_ASSERT(condition)  /
 LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition
#define CHECK(condition)  /
 LOG_IF(FATAL, !(condition)) /
 << "Check failed: " #condition " "

} /* namespace FrameWork */
#endif /* LOGGER_H_ */

 main.cpp

 

復制代碼 代碼如下:

 #include <iostream>
#include "Logger.h"
using namespace std;
using namespace FrameWork;
int main(int argc,char* argv[]) {
 InitLogging(argv[0],INFO,"./log/test");
 cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
 LOG(INFO)<<"info test";
 LOG(WARN)<<"WARN TEST %d"<<20;
 LOG(ERROR)<<"Error test %d %s"<<20<<"nihao";

 Logger::GetInstance().Error("error test common");
 Logger::GetInstance().Fatal("fatal test common %d ",100);
 Logger::GetInstance().Info("info test normal %d %s ",50,"zhongguoren");
 return 0;
}
 

 Mutex.h

 

復制代碼 代碼如下:

 #ifndef MUTEX_H_
#define MUTEX_H_
#include <pthread.h>
#include <stdlib.h>
namespace FrameWork {
typedef pthread_mutex_t MutexType;

class Mutex {
public:
 // Create a Mutex that is not held by anybody.  This constructor is
 // typically used for Mutexes allocated on the heap or the stack.
 // See below for a recommendation for constructing global Mutex
 // objects.
 inline Mutex();

 // Destructor
 inline ~Mutex();

 inline void Lock();    // Block if needed until free then acquire exclusively
 inline void Unlock();  // Release a lock acquired via Lock()
 inline bool TryLock(); // If free, Lock() and return true, else return false
 // Note that on systems that don't support read-write locks, these may
 // be implemented as synonyms to Lock() and Unlock().  So you can use
 // these for efficiency, but don't use them anyplace where being able
 // to do shared reads is necessary to avoid deadlock.
 inline void ReaderLock();   // Block until free or shared then acquire a share
 inline void ReaderUnlock(); // Release a read share of this Mutex
 inline void WriterLock() { Lock(); }     // Acquire an exclusive lock
 inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock()

 // TODO(hamaji): Do nothing, implement correctly.
 inline void AssertHeld() {}
private:
 MutexType mutex_;
 // We want to make sure that the compiler sets is_safe_ to true only
 // when we tell it to, and never makes assumptions is_safe_ is
 // always true.  volatile is the most reliable way to do that.
 volatile bool is_safe_;

 inline void SetIsSafe() { is_safe_ = true; }

 // Catch the error of writing Mutex when intending MutexLock.
 Mutex(Mutex* /*ignored*/) {}
 // Disallow "evil" constructors
 Mutex(const Mutex&);
 void operator=(const Mutex&);
};
#define SAFE_PTHREAD(fncall)  do {   /* run fncall if is_safe_ is true */  /
 if (is_safe_ && fncall(&mutex_) != 0) abort();                           /
 } while (0)

 Mutex::Mutex()             {
  SetIsSafe();
  if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
 }
 Mutex::~Mutex()            { SAFE_PTHREAD(pthread_mutex_destroy); }
 void Mutex::Lock()         { SAFE_PTHREAD(pthread_mutex_lock); }
 void Mutex::Unlock()       { SAFE_PTHREAD(pthread_mutex_unlock); }
 bool Mutex::TryLock()      { return is_safe_ ?
  pthread_mutex_trylock(&mutex_) == 0 : true; }
 void Mutex::ReaderLock()   { Lock(); }
 void Mutex::ReaderUnlock() { Unlock(); }
 class MutexLock {
 public:
  explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); }
  ~MutexLock() { mu_->Unlock(); }
 private:
  Mutex * const mu_;
  // Disallow "evil" constructors
  MutexLock(const MutexLock&);
  void operator=(const MutexLock&);
 };

 // ReaderMutexLock and WriterMutexLock do the same, for rwlocks
 class ReaderMutexLock {
 public:
  explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); }
  ~ReaderMutexLock() { mu_->ReaderUnlock(); }
 private:
  Mutex * const mu_;
  // Disallow "evil" constructors
  ReaderMutexLock(const ReaderMutexLock&);
  void operator=(const ReaderMutexLock&);
 };

 class WriterMutexLock {
 public:
  explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); }
  ~WriterMutexLock() { mu_->WriterUnlock(); }
 private:
  Mutex * const mu_;
  // Disallow "evil" constructors
  WriterMutexLock(const WriterMutexLock&);
  void operator=(const WriterMutexLock&);
 };
} /* namespace FrameWork */
#endif /* MUTEX_H_ */
 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品免费观看在线| www.日韩系列| 欧洲午夜精品久久久| 亚洲天堂久久av| 欧美日韩国产丝袜美女| 91精品一区二区| 亚洲欧美制服中文字幕| 国产精品99免视看9| 国产一区二区三区在线观看视频| 日韩av电影国产| 黄色成人在线免费| 91香蕉国产在线观看| 2019中文字幕在线观看| 国产精品福利片| 亚洲欧美另类在线观看| 欧美极品xxxx| 2019av中文字幕| 国产精品综合不卡av| 国产欧美在线视频| 国产精品久久国产精品99gif| 欧美日韩亚洲视频| 久久91精品国产91久久久| 国产美女久久精品香蕉69| 在线播放日韩专区| 久久久成人av| 97国产精品视频人人做人人爱| 欧美国产极速在线| 92裸体在线视频网站| 欧美日韩国产一区二区三区| 中文字幕欧美日韩精品| 国产亚洲欧美另类中文| 国产精品自产拍在线观| 国产精品旅馆在线| 91精品国产综合久久久久久蜜臀| 国产精品美腿一区在线看| 亚洲欧美日本伦理| 日韩在线观看高清| 欧美综合第一页| 97精品视频在线播放| 九九热精品在线| 亚洲成avwww人| 欧美日韩国产在线看| 伊人一区二区三区久久精品| 日韩第一页在线| 亚洲精品自拍偷拍| 国产欧美日韩91| 国产精品一区二区电影| 国产福利精品av综合导导航| 日韩在线观看精品| 欧美黑人性视频| 欧美午夜精品在线| 国产成人福利夜色影视| xxxxxxxxx欧美| 日韩在线免费观看视频| 日本视频久久久| 国产精品久久久久久久久久久久久| 亚洲电影免费在线观看| 欧美高清自拍一区| 欧美性高潮在线| 欧美精品福利视频| 欧美另类xxx| 精品日韩美女的视频高清| 亚洲午夜精品久久久久久久久久久久| 日韩av免费在线观看| 欧美日韩亚洲网| 欧美视频中文字幕在线| 日韩电影网在线| 2021国产精品视频| 全色精品综合影院| 亚洲精品一区av在线播放| 国产精品网红直播| 欧美电影免费在线观看| 亚洲黄色www| 日韩免费在线播放| 日韩网站免费观看| 成人有码视频在线播放| 国产精品高潮呻吟视频| 欧美精品久久久久| 欧美成人剧情片在线观看| 亚洲欧洲国产伦综合| 久久国产色av| 伊人成人开心激情综合网| 欧美日韩一二三四五区| 精品国产乱码久久久久久婷婷| 色小说视频一区| 日韩欧亚中文在线| 亚洲电影免费观看高清完整版在线观看| 国产精品福利无圣光在线一区| 俺去亚洲欧洲欧美日韩| 97免费在线视频| 国产不卡在线观看| 国产精品人成电影在线观看| 91九色单男在线观看| 97碰碰碰免费色视频| 欧美一区二区三区精品电影| 91精品久久久久久久久久| 黑人精品xxx一区一二区| 亚洲国产精品悠悠久久琪琪| 日本精品免费观看| 色偷偷亚洲男人天堂| 亚洲理论片在线观看| 丝袜一区二区三区| 日韩精品高清视频| 欧美极品美女电影一区| 午夜欧美不卡精品aaaaa| 992tv在线成人免费观看| 亚洲国产成人精品久久久国产成人一区| 91在线视频成人| 伊人激情综合网| 超薄丝袜一区二区| 日韩精品免费一线在线观看| 日本精品久久中文字幕佐佐木| 亚洲人成免费电影| 97人人做人人爱| 91精品国产91久久久久福利| 久久亚洲综合国产精品99麻豆精品福利| 国产一区二区三区三区在线观看| 国产一区二区三区高清在线观看| 久久久中文字幕| 91久久精品国产91久久| 欧洲成人在线观看| 国产区亚洲区欧美区| 国产精品入口日韩视频大尺度| 国产精品久久久久av| 欧美在线激情视频| 亚洲系列中文字幕| 欧美福利视频在线观看| 亚洲国产免费av| 欧美性xxxxxxxxx| 亚洲天天在线日亚洲洲精| 久久久久久久电影一区| 日本精品久久久| 国产精品久久久久不卡| 欧美日韩国产在线| 国产精品视频在线观看| yellow中文字幕久久| 欧美丰满少妇xxxx| 久久久这里只有精品视频| www.欧美免费| 97视频在线观看免费高清完整版在线观看| 欧美日韩在线免费观看| 欧美日韩高清区| 神马国产精品影院av| 国内成人精品视频| 欧美成人一二三| 国产精品欧美久久久| 日韩一区视频在线| 国产丝袜高跟一区| 亚洲欧美激情视频| 欧美高清视频在线观看| 精品一区二区三区四区| 在线视频中文亚洲| 亚洲福利在线看| 午夜欧美大片免费观看| 26uuu亚洲伊人春色| 成人美女av在线直播| 欧美国产在线电影| 亚洲一级免费视频| 久久久久久久久中文字幕| 久久久久久噜噜噜久久久精品| 黄网站色欧美视频| 国产精品第一区| 日韩二区三区在线| 亚洲xxx视频|