<commit_before>// @(#)root/base:$Name:  $:$Id: TAlienSystem.cxx,v 1.1 2006/05/26 16:55:04 rdm Exp $
// Author: Andreas Peters   15/05/2006

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TAlienSystem                                                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include <errno.h>

#include "Riostream.h"
#include "TAlienSystem.h"
#include "TError.h"
#include "TUrl.h"
#include "TGrid.h"
#include "gapi_dir_operations.h"
#include "gapi_file_operations.h"
#include "gapi_stat.h"

ClassImp(TAlienSystem)

//______________________________________________________________________________
TAlienSystem::TAlienSystem(const char *name, const char *title) : TSystem(name, title)
{
   // Create a new OS interface.
}

//______________________________________________________________________________
TAlienSystem::~TAlienSystem()
{
   // Delete the OS interface.
}

//______________________________________________________________________________
Bool_t TAlienSystem::Init()
{
   // Initialize the OS interface.
  return kTRUE;
}

//______________________________________________________________________________
int TAlienSystem::MakeDirectory(const char* dirname)
{
   // Make a directory. Returns 0 in case of success and
   // -1 if the directory could not be created (either already exists or
   // illegal path name).

  if (!gGrid)
    return -1;

  if (strcmp(gGrid->GetGrid(),"alien")) {
    Error("TAlienSystem","You are not connected to AliEn");
    return -1;
  }

  TUrl url(dirname);
  if (strcmp(url.GetProtocol(),"alien")) {
    Info("OpenDirectory","Assuming an AliEn URL alien://%s",dirname);
    url.SetProtocol("alien",kTRUE);
  }
  return gapi_mkdir(url.GetUrl(),0);
}

//______________________________________________________________________________
void *TAlienSystem::OpenDirectory(const char* name)
{
   // Open a directory. Returns 0 if directory does not exist.
   TUrl url(name);
   if (strcmp(url.GetProtocol(),"alien")) {
     Info("OpenDirectory","Assuming an AliEn URL alien://%s",name);
     url.SetProtocol("alien",kTRUE);
   }
   return (void*) gapi_opendir(url.GetUrl());

   AbstractMethod("OpenDirectory");
   return 0;
}

//______________________________________________________________________________
void TAlienSystem::FreeDirectory(void* ptr)
{
   // Free a directory.
   gapi_closedir( (GAPI_DIR*)ptr);
   return;
   AbstractMethod("FreeDirectory");
}

//______________________________________________________________________________
const char *TAlienSystem::GetDirEntry(void* ptr)
{
   // Get a directory entry. Returns 0 if no more entries.
   struct dirent* retdir;
   retdir = gapi_readdir( (GAPI_DIR*) ptr);
   //   AbstractMethod("GetDirEntry");
   if (retdir)
     return retdir->d_name;
   return 0;
}

//______________________________________________________________________________
Bool_t TAlienSystem::ChangeDirectory(const char* dirname)
{
   // Change directory.
   //   AbstractMethod("ChangeDirectory");
   //   return kFALSE;

  TUrl url(dirname);
  if (strcmp(url.GetProtocol(),"alien")) {
    Info("OpenDirectory","Assuming an AliEn URL alien://%s",dirname);
    url.SetProtocol("alien",kTRUE);
  }
  return gapi_chdir(url.GetUrl());
  //  return gGrid->Cd(url.GetFile(),kFALSE);
}

//______________________________________________________________________________
const char *TAlienSystem::WorkingDirectory()
{
   // Return working directory.
  return gapi_getcwd(fWorkingDirectory,1024);
}

//______________________________________________________________________________
const char *TAlienSystem::HomeDirectory(const char*)
{
   // Return the user's home directory.
  if (!gGrid)
    return 0;

  if (strcmp(gGrid->GetGrid(),"alien")) {
    Error("TAlienSystem","You are not connected to AliEn");
    return 0;
  }
  return (gGrid->GetHomeDirectory());
}

//______________________________________________________________________________
int TAlienSystem::mkdir(const char *name, Bool_t recursive)
{
   // Make a file system directory. Returns 0 in case of success and
   // -1 if the directory could not be created (either already exists or
   // illegal path name).
   // If 'recursive' is true, makes parent directories as needed.

   if (recursive) {
      TString dirname = DirName(name);
      if (dirname.Length()==0) {
         // well we should not have to make the root of the file system!
         // (and this avoid infinite recursions!)
         return -1;
      }
      if (AccessPathName(dirname, kFileExists)) {
         int res = mkdir(dirname, kTRUE);
         if (res) return res;
      }
      if (!AccessPathName(name, kFileExists)) {
         return -1;
      }
   }

   return MakeDirectory(name);
}

//______________________________________________________________________________
int TAlienSystem::CopyFile(const char *, const char *, Bool_t)
{
   // Copy a file. If overwrite is true and file already exists the
   // file will be overwritten. Returns 0 when successful, -1 in case
   // of failure, -2 in case the file already exists and overwrite was false.

   AbstractMethod("CopyFile");
   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Rename(const char *oldname, const char *newname)
{
   // Rename a file.
   return gapi_rename(oldname,newname);
   //  AbstractMethod("Rename");
   //   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Link(const char *, const char *)
{
   // Create a link from file1 to file2.

   AbstractMethod("Link");
   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Symlink(const char *, const char *)
{
   // Create a symbolic link from file1 to file2.

   AbstractMethod("Symlink");
   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Unlink(const char * filename)
{
   // Unlink, i.e. remove, a file.

   return gapi_unlink(filename);
   //   AbstractMethod("Unlink");
   //   return -1;
}

//______________________________________________________________________________
int TAlienSystem::GetPathInfo(const char *path, Long_t *id, Long_t *size,
                         Long_t *flags, Long_t *modtime)
{
   // Get info about a file: id, size, flags, modification time.
   // Id      is (statbuf.st_dev << 24) + statbuf.st_ino
   // Size    is the file size
   // Flags   is file type: 0 is regular file, bit 0 set executable,
   //                       bit 1 set directory, bit 2 set special file
   //                       (socket, fifo, pipe, etc.)
   // Modtime is modification time.
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   Long64_t lsize;

   int res = GetPathInfo(path, id, &lsize, flags, modtime);

   if (res == 0 && size) {
      if (sizeof(Long_t) == 4 && lsize > kMaxInt) {
         Error("GetPathInfo", "file %s > 2 GB, use GetPathInfo() with Long64_t size", path);
         *size = kMaxInt;
      } else {
         *size = (Long_t)lsize;
      }
   }

   return res;
}

//______________________________________________________________________________
int TAlienSystem::GetPathInfo(const char *path, Long_t *id, Long64_t *size,
                         Long_t *flags, Long_t *modtime)
{
   // Get info about a file: id, size, flags, modification time.
   // Id      is (statbuf.st_dev << 24) + statbuf.st_ino
   // Size    is the file size
   // Flags   is file type: 0 is regular file, bit 0 set executable,
   //                       bit 1 set directory, bit 2 set special file
   //                       (socket, fifo, pipe, etc.)
   // Modtime is modification time.
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   FileStat_t buf;

   int res = GetPathInfo(path, buf);

   if (res == 0) {
      if (id)
         *id = (buf.fDev << 24) + buf.fIno;
      if (size)
         *size = buf.fSize;
      if (modtime)
         *modtime = buf.fMtime;
      if (flags) {
         *flags = 0;
         if (buf.fMode & (kS_IXUSR|kS_IXGRP|kS_IXOTH))
            *flags |= 1;
         if (R_ISDIR(buf.fMode))
            *flags |= 2;
         if (!R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode))
            *flags |= 4;
      }
   }

   return res;
}

//______________________________________________________________________________
int TAlienSystem::GetPathInfo(const char *path, FileStat_t &buf)
{
   // Get info about a file. Info is returned in the form of a FileStat_t
   // structure (see TSystem.h).
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   //   AbstractMethod("GetPathInfo(const char*, FileStat_t&)");
  return AlienFilestat(path,buf);
}

//______________________________________________________________________________
int TAlienSystem::AlienFilestat(const char *fpath, FileStat_t &buf)
{
   // Get info about a file. Info is returned in the form of a FileStat_t
   // structure (see TSystem.h).
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   TUrl url(fpath);
   if (strcmp(url.GetProtocol(),"alien")) {
     Info("AlienFilestat","Assuming an AliEn URL alien://%s",fpath);
     url.SetProtocol("alien",kTRUE);
   }
#if defined(R__SEEK64)
   struct stat64 sbuf;
   if ((gapi_lstat(url.GetUrl(), (struct GAPI_STAT*)(&sbuf))) == 0) {
#else
   struct stat sbuf;
   if ((gapi_lstat(url.GetUrl(), (struct GAPI_STAT*)(&sbuf))) == 0) {
#endif
      buf.fIsLink = S_ISLNK(sbuf.st_mode);
      buf.fDev   = sbuf.st_dev;
      buf.fIno   = sbuf.st_ino;
      buf.fMode  = sbuf.st_mode;
      buf.fUid   = sbuf.st_uid;
      buf.fGid   = sbuf.st_gid;
      buf.fSize  = sbuf.st_size;
      buf.fMtime = sbuf.st_mtime;

      return 0;
   }
   return 1;
}

//______________________________________________________________________________
int TAlienSystem::GetFsInfo(const char *, Long_t *, Long_t *, Long_t *, Long_t *)
{
   // Get info about a file system: fs type, block size, number of blocks,
   // number of free blocks.

   AbstractMethod("GetFsInfo");
   return 1;
}

//______________________________________________________________________________
int TAlienSystem::Chmod(const char *file, UInt_t mode)
{
   // Set the file permission bits. Returns -1 in case or error, 0 otherwise.
   TUrl url(file);
   if (strcmp(url.GetProtocol(),"alien")) {
     Info("AlienFilestat","Assuming an AliEn URL alien://%s",file);
     url.SetProtocol("alien",kTRUE);
   }
   return gapi_chmod(url.GetUrl(),mode);
 }

//______________________________________________________________________________
int TAlienSystem::Umask(Int_t)
{
   // Set the process file creation mode mask.

   AbstractMethod("Umask");
   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Utime(const char *, Long_t, Long_t)
{
   // Set the a files modification and access times. If actime = 0 it will be
   // set to the modtime. Returns 0 on success and -1 in case of error.

   AbstractMethod("Utime");
   return -1;
}

//______________________________________________________________________________
char *TAlienSystem::Which(const char *, const char *, EAccessMode)
{
   // Find location of file in a search path. User must delete returned string.
   // Returns 0 in case file is not found.

   AbstractMethod("Which");
   return 0;
}

//---- Users & Groups ----------------------------------------------------------

//______________________________________________________________________________
Int_t TAlienSystem::GetUid(const char * /*user*/)
{
   // Returns the user's id. If user = 0, returns current user's id.

   AbstractMethod("GetUid");
   return 0;
}

//______________________________________________________________________________
Int_t TAlienSystem::GetEffectiveUid()
{
   // Returns the effective user id. The effective id corresponds to the
   // set id bit on the file being executed.

   AbstractMethod("GetEffectiveUid");
   return 0;
}

//______________________________________________________________________________
Int_t TAlienSystem::GetGid(const char * /*group*/)
{
   // Returns the group's id. If group = 0, returns current user's group.

   AbstractMethod("GetGid");
   return 0;
}

//______________________________________________________________________________
Int_t TAlienSystem::GetEffectiveGid()
{
   // Returns the effective group id. The effective group id corresponds
   // to the set id bit on the file being executed.

   AbstractMethod("GetEffectiveGid");
   return 0;
}

//______________________________________________________________________________
UserGroup_t *TAlienSystem::GetUserInfo(Int_t /*uid*/)
{
   // Returns all user info in the UserGroup_t structure. The returned
   // structure must be deleted by the user. In case of error 0 is returned.

   AbstractMethod("GetUserInfo");
   return 0;
}

//______________________________________________________________________________
UserGroup_t *TAlienSystem::GetUserInfo(const char * /*user*/)
{
   // Returns all user info in the UserGroup_t structure. If user = 0, returns
   // current user's id info. The returned structure must be deleted by the
   // user. In case of error 0 is returned.

   AbstractMethod("GetUserInfo");
   return 0;
}

//______________________________________________________________________________
UserGroup_t *TAlienSystem::GetGroupInfo(Int_t /*gid*/)
{
   // Returns all group info in the UserGroup_t structure. The only active
   // fields in the UserGroup_t structure for this call are:
   //    fGid and fGroup
   // The returned structure must be deleted by the user. In case of
   // error 0 is returned.

   AbstractMethod("GetGroupInfo");
   return 0;
}

//______________________________________________________________________________
UserGroup_t *TAlienSystem::GetGroupInfo(const char * /*group*/)
{
   // Returns all group info in the UserGroup_t structure. The only active
   // fields in the UserGroup_t structure for this call are:
   //    fGid and fGroup
   // If group = 0, returns current user's group. The returned structure
   // must be deleted by the user. In case of error 0 is returned.

   AbstractMethod("GetGroupInfo");
   return 0;
}

<commit_msg>From Andreas: correct type casting.<commit_after>// @(#)root/base:$Name:  $:$Id: TAlienSystem.cxx,v 1.2 2006/05/30 15:34:17 rdm Exp $
// Author: Andreas Peters   15/05/2006

/*************************************************************************
 * Copyright (C) 1995-2006, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TAlienSystem                                                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include <errno.h>

#include "Riostream.h"
#include "TAlienSystem.h"
#include "TError.h"
#include "TUrl.h"
#include "TGrid.h"
#include "gapi_dir_operations.h"
#include "gapi_file_operations.h"
#include "gapi_stat.h"

ClassImp(TAlienSystem)

//______________________________________________________________________________
TAlienSystem::TAlienSystem(const char *name, const char *title) : TSystem(name, title)
{
   // Create a new OS interface.
}

//______________________________________________________________________________
TAlienSystem::~TAlienSystem()
{
   // Delete the OS interface.
}

//______________________________________________________________________________
Bool_t TAlienSystem::Init()
{
   // Initialize the OS interface.
  return kTRUE;
}

//______________________________________________________________________________
int TAlienSystem::MakeDirectory(const char* dirname)
{
   // Make a directory. Returns 0 in case of success and
   // -1 if the directory could not be created (either already exists or
   // illegal path name).

  if (!gGrid)
    return -1;

  if (strcmp(gGrid->GetGrid(),"alien")) {
    Error("TAlienSystem","You are not connected to AliEn");
    return -1;
  }

  TUrl url(dirname);
  if (strcmp(url.GetProtocol(),"alien")) {
    Info("OpenDirectory","Assuming an AliEn URL alien://%s",dirname);
    url.SetProtocol("alien",kTRUE);
  }
  return gapi_mkdir(url.GetUrl(),0);
}

//______________________________________________________________________________
void *TAlienSystem::OpenDirectory(const char* name)
{
   // Open a directory. Returns 0 if directory does not exist.
   TUrl url(name);
   if (strcmp(url.GetProtocol(),"alien")) {
     Info("OpenDirectory","Assuming an AliEn URL alien://%s",name);
     url.SetProtocol("alien",kTRUE);
   }
   return (void*) gapi_opendir(url.GetUrl());

   AbstractMethod("OpenDirectory");
   return 0;
}

//______________________________________________________________________________
void TAlienSystem::FreeDirectory(void* ptr)
{
   // Free a directory.
   gapi_closedir( (GAPI_DIR*)ptr);
   return;
   AbstractMethod("FreeDirectory");
}

//______________________________________________________________________________
const char *TAlienSystem::GetDirEntry(void* ptr)
{
   // Get a directory entry. Returns 0 if no more entries.
   struct dirent* retdir;
   retdir = gapi_readdir( (GAPI_DIR*) ptr);
   //   AbstractMethod("GetDirEntry");
   if (retdir)
     return retdir->d_name;
   return 0;
}

//______________________________________________________________________________
Bool_t TAlienSystem::ChangeDirectory(const char* dirname)
{
   // Change directory.
   //   AbstractMethod("ChangeDirectory");
   //   return kFALSE;

  TUrl url(dirname);
  if (strcmp(url.GetProtocol(),"alien")) {
    Info("OpenDirectory","Assuming an AliEn URL alien://%s",dirname);
    url.SetProtocol("alien",kTRUE);
  }
  return gapi_chdir(url.GetUrl());
  //  return gGrid->Cd(url.GetFile(),kFALSE);
}

//______________________________________________________________________________
const char *TAlienSystem::WorkingDirectory()
{
   // Return working directory.
  return gapi_getcwd(fWorkingDirectory,1024);
}

//______________________________________________________________________________
const char *TAlienSystem::HomeDirectory(const char*)
{
   // Return the user's home directory.
  if (!gGrid)
    return 0;

  if (strcmp(gGrid->GetGrid(),"alien")) {
    Error("TAlienSystem","You are not connected to AliEn");
    return 0;
  }
  return (gGrid->GetHomeDirectory());
}

//______________________________________________________________________________
int TAlienSystem::mkdir(const char *name, Bool_t recursive)
{
   // Make a file system directory. Returns 0 in case of success and
   // -1 if the directory could not be created (either already exists or
   // illegal path name).
   // If 'recursive' is true, makes parent directories as needed.

   if (recursive) {
      TString dirname = DirName(name);
      if (dirname.Length()==0) {
         // well we should not have to make the root of the file system!
         // (and this avoid infinite recursions!)
         return -1;
      }
      if (AccessPathName(dirname, kFileExists)) {
         int res = mkdir(dirname, kTRUE);
         if (res) return res;
      }
      if (!AccessPathName(name, kFileExists)) {
         return -1;
      }
   }

   return MakeDirectory(name);
}

//______________________________________________________________________________
int TAlienSystem::CopyFile(const char *, const char *, Bool_t)
{
   // Copy a file. If overwrite is true and file already exists the
   // file will be overwritten. Returns 0 when successful, -1 in case
   // of failure, -2 in case the file already exists and overwrite was false.

   AbstractMethod("CopyFile");
   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Rename(const char *oldname, const char *newname)
{
   // Rename a file.
   return gapi_rename(oldname,newname);
   //  AbstractMethod("Rename");
   //   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Link(const char *, const char *)
{
   // Create a link from file1 to file2.

   AbstractMethod("Link");
   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Symlink(const char *, const char *)
{
   // Create a symbolic link from file1 to file2.

   AbstractMethod("Symlink");
   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Unlink(const char * filename)
{
   // Unlink, i.e. remove, a file.

   return gapi_unlink(filename);
   //   AbstractMethod("Unlink");
   //   return -1;
}

//______________________________________________________________________________
int TAlienSystem::GetPathInfo(const char *path, Long_t *id, Long_t *size,
                         Long_t *flags, Long_t *modtime)
{
   // Get info about a file: id, size, flags, modification time.
   // Id      is (statbuf.st_dev << 24) + statbuf.st_ino
   // Size    is the file size
   // Flags   is file type: 0 is regular file, bit 0 set executable,
   //                       bit 1 set directory, bit 2 set special file
   //                       (socket, fifo, pipe, etc.)
   // Modtime is modification time.
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   Long64_t lsize;

   int res = GetPathInfo(path, id, &lsize, flags, modtime);

   if (res == 0 && size) {
      if (sizeof(Long_t) == 4 && lsize > kMaxInt) {
         Error("GetPathInfo", "file %s > 2 GB, use GetPathInfo() with Long64_t size", path);
         *size = kMaxInt;
      } else {
         *size = (Long_t)lsize;
      }
   }

   return res;
}

//______________________________________________________________________________
int TAlienSystem::GetPathInfo(const char *path, Long_t *id, Long64_t *size,
                         Long_t *flags, Long_t *modtime)
{
   // Get info about a file: id, size, flags, modification time.
   // Id      is (statbuf.st_dev << 24) + statbuf.st_ino
   // Size    is the file size
   // Flags   is file type: 0 is regular file, bit 0 set executable,
   //                       bit 1 set directory, bit 2 set special file
   //                       (socket, fifo, pipe, etc.)
   // Modtime is modification time.
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   FileStat_t buf;

   int res = GetPathInfo(path, buf);

   if (res == 0) {
      if (id)
         *id = (buf.fDev << 24) + buf.fIno;
      if (size)
         *size = buf.fSize;
      if (modtime)
         *modtime = buf.fMtime;
      if (flags) {
         *flags = 0;
         if (buf.fMode & (kS_IXUSR|kS_IXGRP|kS_IXOTH))
            *flags |= 1;
         if (R_ISDIR(buf.fMode))
            *flags |= 2;
         if (!R_ISREG(buf.fMode) && !R_ISDIR(buf.fMode))
            *flags |= 4;
      }
   }

   return res;
}

//______________________________________________________________________________
int TAlienSystem::GetPathInfo(const char *path, FileStat_t &buf)
{
   // Get info about a file. Info is returned in the form of a FileStat_t
   // structure (see TSystem.h).
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   //   AbstractMethod("GetPathInfo(const char*, FileStat_t&)");
  return AlienFilestat(path,buf);
}

//______________________________________________________________________________
int TAlienSystem::AlienFilestat(const char *fpath, FileStat_t &buf)
{
   // Get info about a file. Info is returned in the form of a FileStat_t
   // structure (see TSystem.h).
   // The function returns 0 in case of success and 1 if the file could
   // not be stat'ed.

   TUrl url(fpath);
   if (strcmp(url.GetProtocol(),"alien")) {
     Info("AlienFilestat","Assuming an AliEn URL alien://%s",fpath);
     url.SetProtocol("alien",kTRUE);
   }
#if defined(R__SEEK64)
   struct stat64 sbuf;
   if ((gapi_lstat(url.GetUrl(), (GAPI_STAT*)(&sbuf))) == 0) {
#else
   struct stat sbuf;
   if ((gapi_lstat(url.GetUrl(), (GAPI_STAT*)(&sbuf))) == 0) {
#endif
      buf.fIsLink = S_ISLNK(sbuf.st_mode);
      buf.fDev   = sbuf.st_dev;
      buf.fIno   = sbuf.st_ino;
      buf.fMode  = sbuf.st_mode;
      buf.fUid   = sbuf.st_uid;
      buf.fGid   = sbuf.st_gid;
      buf.fSize  = sbuf.st_size;
      buf.fMtime = sbuf.st_mtime;

      return 0;
   }
   return 1;
}

//______________________________________________________________________________
int TAlienSystem::GetFsInfo(const char *, Long_t *, Long_t *, Long_t *, Long_t *)
{
   // Get info about a file system: fs type, block size, number of blocks,
   // number of free blocks.

   AbstractMethod("GetFsInfo");
   return 1;
}

//______________________________________________________________________________
int TAlienSystem::Chmod(const char *file, UInt_t mode)
{
   // Set the file permission bits. Returns -1 in case or error, 0 otherwise.
   TUrl url(file);
   if (strcmp(url.GetProtocol(),"alien")) {
     Info("AlienFilestat","Assuming an AliEn URL alien://%s",file);
     url.SetProtocol("alien",kTRUE);
   }
   return gapi_chmod(url.GetUrl(),mode);
 }

//______________________________________________________________________________
int TAlienSystem::Umask(Int_t)
{
   // Set the process file creation mode mask.

   AbstractMethod("Umask");
   return -1;
}

//______________________________________________________________________________
int TAlienSystem::Utime(const char *, Long_t, Long_t)
{
   // Set the a files modification and access times. If actime = 0 it will be
   // set to the modtime. Returns 0 on success and -1 in case of error.

   AbstractMethod("Utime");
   return -1;
}

//______________________________________________________________________________
char *TAlienSystem::Which(const char *, const char *, EAccessMode)
{
   // Find location of file in a search path. User must delete returned string.
   // Returns 0 in case file is not found.

   AbstractMethod("Which");
   return 0;
}

//---- Users & Groups ----------------------------------------------------------

//______________________________________________________________________________
Int_t TAlienSystem::GetUid(const char * /*user*/)
{
   // Returns the user's id. If user = 0, returns current user's id.

   AbstractMethod("GetUid");
   return 0;
}

//______________________________________________________________________________
Int_t TAlienSystem::GetEffectiveUid()
{
   // Returns the effective user id. The effective id corresponds to the
   // set id bit on the file being executed.

   AbstractMethod("GetEffectiveUid");
   return 0;
}

//______________________________________________________________________________
Int_t TAlienSystem::GetGid(const char * /*group*/)
{
   // Returns the group's id. If group = 0, returns current user's group.

   AbstractMethod("GetGid");
   return 0;
}

//______________________________________________________________________________
Int_t TAlienSystem::GetEffectiveGid()
{
   // Returns the effective group id. The effective group id corresponds
   // to the set id bit on the file being executed.

   AbstractMethod("GetEffectiveGid");
   return 0;
}

//______________________________________________________________________________
UserGroup_t *TAlienSystem::GetUserInfo(Int_t /*uid*/)
{
   // Returns all user info in the UserGroup_t structure. The returned
   // structure must be deleted by the user. In case of error 0 is returned.

   AbstractMethod("GetUserInfo");
   return 0;
}

//______________________________________________________________________________
UserGroup_t *TAlienSystem::GetUserInfo(const char * /*user*/)
{
   // Returns all user info in the UserGroup_t structure. If user = 0, returns
   // current user's id info. The returned structure must be deleted by the
   // user. In case of error 0 is returned.

   AbstractMethod("GetUserInfo");
   return 0;
}

//______________________________________________________________________________
UserGroup_t *TAlienSystem::GetGroupInfo(Int_t /*gid*/)
{
   // Returns all group info in the UserGroup_t structure. The only active
   // fields in the UserGroup_t structure for this call are:
   //    fGid and fGroup
   // The returned structure must be deleted by the user. In case of
   // error 0 is returned.

   AbstractMethod("GetGroupInfo");
   return 0;
}

//______________________________________________________________________________
UserGroup_t *TAlienSystem::GetGroupInfo(const char * /*group*/)
{
   // Returns all group info in the UserGroup_t structure. The only active
   // fields in the UserGroup_t structure for this call are:
   //    fGid and fGroup
   // If group = 0, returns current user's group. The returned structure
   // must be deleted by the user. In case of error 0 is returned.

   AbstractMethod("GetGroupInfo");
   return 0;
}

<|endoftext|>


<commit_before>#include "slist_parser.h"
#include "slist_log.h"

#include <cassert>
#include <cctype>
#include <fstream>
#include <sstream>
#include <stack>
#include <iostream>

namespace
{
	bool get_next_char(std::istream& in, char& ch);
	char peek_next_char(std::istream& in);

	bool parse_list(std::istream& in, slist::node_ptr result);
	bool parse_token(std::istream& in, slist::node_ptr& result);
	bool parse_string(std::istream& in, slist::node_ptr& result);
	bool parse_comment(std::istream& in);

	slist::node_type find_type(const std::string& str);
	std::string type_to_string(slist::node_type type);
}

namespace slist
{
	node_ptr parse(const std::string& str)
	{
		std::istringstream in(str);
		in >> std::noskipws;

		node_ptr result(new node);
		result->type = node_type::pair;

		char ch;
		std::string tok;

		while (true)
		{
			if (!get_next_char(in, ch))
			{
				break;
			}

			in.putback(ch);
			if (ch == '(')
			{
				node_ptr list(new node);
				list->type = node_type::pair;

				if (parse_list(in, list))
				{
					result->append(list);
				}
			}
			else if(ch == '"')
			{
				in.putback(ch);
				node_ptr string_node(new node);
				if (parse_string(in, string_node))
				{
					result->append(string_node);
				}
			}
			else if (ch == ';')
			{
				parse_comment(in);
			}
			else
			{
				node_ptr token(new node);
				if (parse_token(in, token))
				{
					result->append(token);
				}
				break;
			}
		}

		return result;
	}

	node_ptr parse_stream(std::istream& in)
	{
		const size_t bufsize = 1024;
		char buf[bufsize];

		std::string str;

		while (!in.eof())
		{
			in.read(buf, bufsize);
			str += std::string(buf, in.gcount());
		}

		return parse(str);
	}

	node_ptr parse_file(const std::string& filename)
	{
		std::ifstream in(filename);
		return parse_stream(in);
	}
}

namespace
{
	bool get_next_char(std::istream& in, char& ch)
	{
		while (in)
		{
			ch = in.get();
			if (std::isspace(ch) == 0)
			{
				return true;
			}
		}
		return false;
	}

	char peek_next_char(std::istream& in)
	{
		return static_cast<char>(in.peek());
	}

	bool parse_list(std::istream& in, slist::node_ptr result)
	{
		using namespace slist;

		std::string tok;
		char ch = 0;
		bool parsed = false;

		get_next_char(in, ch);
		assert(ch == '(');

		// TODO: This is basically 'parse()' repeated here... call it directly instead?

		while (true)
		{
			if (!get_next_char(in, ch))
			{
				break;
			}

			if (ch == '(')
			{
				in.putback(ch);

				node_ptr list(new node);
				list->type = node_type::pair;

				if (parse_list(in, list))
				{
					result->append(list);
				}
			}
			else if (ch == ')')
			{
				parsed = true;
				break;
			}
			else if(ch == '"')
			{
				in.putback(ch);
				node_ptr string_node(new node);
				if (parse_string(in, string_node))
				{
					result->append(string_node);
				}
			}
			else if (ch == ';')
			{
				parse_comment(in);
			}
			else
			{
				in.putback(ch);

				node_ptr token(new node);
				if (parse_token(in, token))
				{
					result->append(token);
				}
			}
		}

		if (!parsed)
		{
            log_errorln(std::string("Parsing failed at char: '") + std::string(&ch, 1));
			return false;
		}

		return true;
	}

	bool parse_token(std::istream& in, slist::node_ptr& result)
	{
		using namespace slist;

		char ch = 0;
		if (get_next_char(in, ch))
		{
			in.putback(ch);

			std::string str;

			while (true)
			{
				in.get(ch);

				if (in && ch == '\'')
				{
					result->type = node_type::pair;

					node_ptr sym(new node);
					sym->type = node_type::name;
					sym->value = "'";

					result->append(sym);

					char next_ch = peek_next_char(in);
					if (next_ch == '(')
					{
						node_ptr sublist(new node);
						sublist->type = node_type::pair;

						if (parse_list(in, sublist))
						{
							result->append(sublist);
						}
					}
					else
					{
						node_ptr subname(new node);
						if (parse_token(in, subname))
						{
							result->append(subname);
						}
					}

                    return true;
				}
				else if (in && ch != '(' && ch != ')' && !std::isspace(ch) && ch != ';')
				{
					str += ch;
				}
				else
				{
					if (ch == '(' || ch == ')' || ch == ';')
					{
						in.putback(ch);
					}
					break;
				}
			}

            result->type = find_type(str);
            result->value = str;

			return true;
		}

		return false;
	}

	bool parse_string(std::istream& in, slist::node_ptr& result)
	{
		using namespace slist;

		char ch = '\0';
		get_next_char(in, ch);
		if (ch == '"')
		{
			std::string str;

			while (true)
			{
				get_next_char(in, ch);

				if (!in)
				{
					break;
				}

				if (ch == '\\' && peek_next_char(in) == '"')
				{
					get_next_char(in, ch);
					str += ch;
				}
				else if (ch == '"')
				{
					break;
				}

				str += ch;
			}

			result->type = node_type::string;
			result->value = str;

			return true;
		}
		return false;
	}

	bool parse_comment(std::istream& in)
	{
		char ch = '\0';
		while (in && ch != '\n')
		{
			in.get(ch);
		}
		return true;
	}

	slist::node_type find_type(const std::string& str)
	{
		using namespace slist;
		node_type type = node_type::empty;

		if (str == "true" || str == "false")
		{
			return node_type::boolean;
		}

		int dot_count = 0;
		bool has_only_digits = false;
		bool has_alpha = false;
		bool is_first_char = true;

		for (char ch : str)
		{
			if (std::isdigit(ch) || ch == '-')
			{
				has_only_digits = !has_alpha;
			}
			else if (ch == '.')
			{
				++dot_count;
			}
			else
			{
				has_alpha = true;
				has_only_digits = false;
			}

			is_first_char = false;
		}

		if (has_only_digits && dot_count == 1)
		{
			type = node_type::number;
		}
		else if (has_only_digits && dot_count == 0)
		{
			type = node_type::integer;
		}
		else
		{
			type = node_type::name;
		}

		return type;
	}
}<commit_msg>Fixed unary '-' issue.<commit_after>#include "slist_parser.h"
#include "slist_log.h"

#include <cassert>
#include <cctype>
#include <fstream>
#include <sstream>
#include <stack>
#include <iostream>

namespace
{
	bool get_next_char(std::istream& in, char& ch);
	char peek_next_char(std::istream& in);

	bool parse_list(std::istream& in, slist::node_ptr result);
	bool parse_token(std::istream& in, slist::node_ptr& result);
	bool parse_string(std::istream& in, slist::node_ptr& result);
	bool parse_comment(std::istream& in);

	slist::node_type find_type(const std::string& str);
	std::string type_to_string(slist::node_type type);
}

namespace slist
{
	node_ptr parse(const std::string& str)
	{
		std::istringstream in(str);
		in >> std::noskipws;

		node_ptr result(new node);
		result->type = node_type::pair;

		char ch;
		std::string tok;

		while (true)
		{
			if (!get_next_char(in, ch))
			{
				break;
			}

			in.putback(ch);
			if (ch == '(')
			{
				node_ptr list(new node);
				list->type = node_type::pair;

				if (parse_list(in, list))
				{
					result->append(list);
				}
			}
			else if(ch == '"')
			{
				in.putback(ch);
				node_ptr string_node(new node);
				if (parse_string(in, string_node))
				{
					result->append(string_node);
				}
			}
			else if (ch == ';')
			{
				parse_comment(in);
			}
			else
			{
				node_ptr token(new node);
				if (parse_token(in, token))
				{
					result->append(token);
				}
				break;
			}
		}

		return result;
	}

	node_ptr parse_stream(std::istream& in)
	{
		const size_t bufsize = 1024;
		char buf[bufsize];

		std::string str;

		while (!in.eof())
		{
			in.read(buf, bufsize);
			str += std::string(buf, in.gcount());
		}

		return parse(str);
	}

	node_ptr parse_file(const std::string& filename)
	{
		std::ifstream in(filename);
		return parse_stream(in);
	}
}

namespace
{
	bool get_next_char(std::istream& in, char& ch)
	{
		while (in)
		{
			ch = in.get();
			if (std::isspace(ch) == 0)
			{
				return true;
			}
		}
		return false;
	}

	char peek_next_char(std::istream& in)
	{
		return static_cast<char>(in.peek());
	}

	bool parse_list(std::istream& in, slist::node_ptr result)
	{
		using namespace slist;

		std::string tok;
		char ch = 0;
		bool parsed = false;

		get_next_char(in, ch);
		assert(ch == '(');

		// TODO: This is basically 'parse()' repeated here... call it directly instead?

		while (true)
		{
			if (!get_next_char(in, ch))
			{
				break;
			}

			if (ch == '(')
			{
				in.putback(ch);

				node_ptr list(new node);
				list->type = node_type::pair;

				if (parse_list(in, list))
				{
					result->append(list);
				}
			}
			else if (ch == ')')
			{
				parsed = true;
				break;
			}
			else if(ch == '"')
			{
				in.putback(ch);
				node_ptr string_node(new node);
				if (parse_string(in, string_node))
				{
					result->append(string_node);
				}
			}
			else if (ch == ';')
			{
				parse_comment(in);
			}
			else
			{
				in.putback(ch);

				node_ptr token(new node);
				if (parse_token(in, token))
				{
					result->append(token);
				}
			}
		}

		if (!parsed)
		{
            log_errorln(std::string("Parsing failed at char: '") + std::string(&ch, 1));
			return false;
		}

		return true;
	}

	bool parse_token(std::istream& in, slist::node_ptr& result)
	{
		using namespace slist;

		char ch = 0;
		if (get_next_char(in, ch))
		{
			in.putback(ch);

			std::string str;

			while (true)
			{
				in.get(ch);

				if (in && ch == '\'')
				{
					result->type = node_type::pair;

					node_ptr sym(new node);
					sym->type = node_type::name;
					sym->value = "'";

					result->append(sym);

					char next_ch = peek_next_char(in);
					if (next_ch == '(')
					{
						node_ptr sublist(new node);
						sublist->type = node_type::pair;

						if (parse_list(in, sublist))
						{
							result->append(sublist);
						}
					}
					else
					{
						node_ptr subname(new node);
						if (parse_token(in, subname))
						{
							result->append(subname);
						}
					}

                    return true;
				}
				else if (in && ch != '(' && ch != ')' && !std::isspace(ch) && ch != ';')
				{
					str += ch;
				}
				else
				{
					if (ch == '(' || ch == ')' || ch == ';')
					{
						in.putback(ch);
					}
					break;
				}
			}

            result->type = find_type(str);
            result->value = str;

			return true;
		}

		return false;
	}

	bool parse_string(std::istream& in, slist::node_ptr& result)
	{
		using namespace slist;

		char ch = '\0';
		get_next_char(in, ch);
		if (ch == '"')
		{
			std::string str;

			while (true)
			{
				get_next_char(in, ch);

				if (!in)
				{
					break;
				}

				if (ch == '\\' && peek_next_char(in) == '"')
				{
					get_next_char(in, ch);
					str += ch;
				}
				else if (ch == '"')
				{
					break;
				}

				str += ch;
			}

			result->type = node_type::string;
			result->value = str;

			return true;
		}
		return false;
	}

	bool parse_comment(std::istream& in)
	{
		char ch = '\0';
		while (in && ch != '\n')
		{
			in.get(ch);
		}
		return true;
	}

	slist::node_type find_type(const std::string& str)
	{
		using namespace slist;
		node_type type = node_type::empty;

		if (str == "true" || str == "false")
		{
			return node_type::boolean;
		}

		int dot_count = 0;
		bool has_only_digits = false;
		bool has_alpha = false;
		bool is_first_char = true;

		for (char ch : str)
		{
			if (std::isdigit(ch))
			{
				has_only_digits = !has_alpha;
			}
			else if (ch == '-')
			{
				if (has_only_digits)
				{
					has_only_digits = false;
					break;
				}
			}
			else if (ch == '.')
			{
				++dot_count;
			}
			else
			{
				has_alpha = true;
				has_only_digits = false;
				break;
			}

			is_first_char = false;
		}

		if (has_only_digits && dot_count == 1)
		{
			type = node_type::number;
		}
		else if (has_only_digits && dot_count == 0)
		{
			type = node_type::integer;
		}
		else
		{
			type = node_type::name;
		}

		return type;
	}
}<|endoftext|>


<commit_before>/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2013-10-26 Martin Siggel <Martin.Siggel@dlr.de>
*
* 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.
*/

#include "CGlogLoggerAdaptor.h"
#include "ITiglLogger.h"

#include <mutex>

#ifdef GLOG_FOUND

// uncomment to enable debugging messages
//#define LOGGER_DEBUG

namespace tigl
{

CGlogLoggerAdaptor::CGlogLoggerAdaptor(PTiglLogger logger)
{
    _mylogger = logger;
}

CGlogLoggerAdaptor::~CGlogLoggerAdaptor()
{
}

void CGlogLoggerAdaptor::Write(bool force_flush,
                               time_t /* timestamp */,
                               const char* message,
                               int message_len)
{
#ifdef LOGGER_DEBUG
    printf("CGlogLoggerAdaptor::Write called. force_flush=%d\n", force_flush);
#endif

    if (_mylogger && message_len > 0) {
        _mutex.lock();
        std::string msg(message, message_len);

        //TODO: determine log level
        TiglLogLevel level = TILOG_INFO;
        if (msg[0] == 'I') {
            level = TILOG_INFO;
        }
        else if (msg[0] == 'E') {
            level = TILOG_ERROR;
        }
        else if (msg[0] == 'W') {
            level = TILOG_WARNING;
        }

        _mylogger->LogMessage(level, msg.c_str());
        _mutex.unlock();
    }
}

// Flush any buffered messages
void CGlogLoggerAdaptor::Flush()
{
#ifdef LOGGER_DEBUG
    printf("CGlogLoggerAdaptor::Flush called.\n");
#endif
}

google::uint32 CGlogLoggerAdaptor::LogSize()
{
#ifdef LOGGER_DEBUG
    printf("CGlogLoggerAdaptor::LogSize called.\n");
#endif
    return 0;
}

} // namespace tigl

#endif // GLOG_FOUND
<commit_msg>use std::lock_guard instead of manual unlocking<commit_after>/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2013-10-26 Martin Siggel <Martin.Siggel@dlr.de>
*
* 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.
*/

#include "CGlogLoggerAdaptor.h"
#include "ITiglLogger.h"

#include <mutex>

#ifdef GLOG_FOUND

// uncomment to enable debugging messages
//#define LOGGER_DEBUG

namespace tigl
{

CGlogLoggerAdaptor::CGlogLoggerAdaptor(PTiglLogger logger)
{
    _mylogger = logger;
}

CGlogLoggerAdaptor::~CGlogLoggerAdaptor()
{
}

void CGlogLoggerAdaptor::Write(bool force_flush,
                               time_t /* timestamp */,
                               const char* message,
                               int message_len)
{
#ifdef LOGGER_DEBUG
    printf("CGlogLoggerAdaptor::Write called. force_flush=%d\n", force_flush);
#endif

    if (_mylogger && message_len > 0) {
        const std::lock_guard<std::mutex> lock(_mutex);
        std::string msg(message, message_len);

        //TODO: determine log level
        TiglLogLevel level = TILOG_INFO;
        if (msg[0] == 'I') {
            level = TILOG_INFO;
        }
        else if (msg[0] == 'E') {
            level = TILOG_ERROR;
        }
        else if (msg[0] == 'W') {
            level = TILOG_WARNING;
        }

        _mylogger->LogMessage(level, msg.c_str());
    }
}

// Flush any buffered messages
void CGlogLoggerAdaptor::Flush()
{
#ifdef LOGGER_DEBUG
    printf("CGlogLoggerAdaptor::Flush called.\n");
#endif
}

google::uint32 CGlogLoggerAdaptor::LogSize()
{
#ifdef LOGGER_DEBUG
    printf("CGlogLoggerAdaptor::LogSize called.\n");
#endif
    return 0;
}

} // namespace tigl

#endif // GLOG_FOUND
<|endoftext|>


<commit_before>/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <string>
#include "util/object_serializer.h"
#include "kernel/expr.h"
#include "kernel/declaration.h"
#include "library/max_sharing.h"
#include "library/kernel_serializer.h"

// Procedures for serializing and deserializing kernel objects (levels, exprs, declarations)
namespace lean {
// Universe level serialization
class level_serializer : public object_serializer<level, level::ptr_hash, level::ptr_eq> {
    typedef object_serializer<level, level::ptr_hash, level::ptr_eq> super;
public:
    void write(level const & l) {
        super::write(l, [&]() {
                serializer & s = get_owner();
                auto k = kind(l);
                s << static_cast<char>(k);
                switch (k) {
                case level_kind::Zero:     break;
                case level_kind::Param:    s << param_id(l);   break;
                case level_kind::Global:   s << global_id(l);  break;
                case level_kind::Meta:     s << meta_id(l);    break;
                case level_kind::Max:      write(max_lhs(l));  write(max_rhs(l)); break;
                case level_kind::IMax:     write(imax_lhs(l)); write(imax_rhs(l)); break;
                case level_kind::Succ:     write(succ_of(l));  break;
                }
            });
    }
};

class level_deserializer : public object_deserializer<level> {
    typedef object_deserializer<level> super;
public:
    level read() {
        return super::read([&]() -> level {
                deserializer & d = get_owner();
                auto k = static_cast<level_kind>(d.read_char());
                switch (k) {
                case level_kind::Zero:
                    return mk_level_zero();
                case level_kind::Param:
                    return mk_param_univ(read_name(d));
                case level_kind::Global:
                    return mk_global_univ(read_name(d));
                case level_kind::Meta:
                    return mk_meta_univ(read_name(d));
                case level_kind::Max: {
                    level lhs = read();
                    return mk_max(lhs, read());
                }
                case level_kind::IMax: {
                    level lhs = read();
                    return mk_imax(lhs, read());
                }
                case level_kind::Succ:
                    return mk_succ(read());
                }
                throw_corrupted_file();
            });
    }
};

struct level_sd {
    unsigned m_s_extid;
    unsigned m_d_extid;
    level_sd() {
        m_s_extid = serializer::register_extension([](){
                return std::unique_ptr<serializer::extension>(new level_serializer());
            });
        m_d_extid = deserializer::register_extension([](){
                return std::unique_ptr<deserializer::extension>(new level_deserializer());
            });
    }
};

static level_sd g_level_sd;

serializer & operator<<(serializer & s, level const & n) {
    s.get_extension<level_serializer>(g_level_sd.m_s_extid).write(n);
    return s;
}

level read_level(deserializer & d) { return d.get_extension<level_deserializer>(g_level_sd.m_d_extid).read(); }

serializer & operator<<(serializer & s, levels const & ls) { return write_list<level>(s, ls); }

levels read_levels(deserializer & d) { return read_list<level>(d, read_level); }

// Expression serialization
typedef std::unordered_map<std::string, macro_definition_cell::reader> macro_readers;
static std::unique_ptr<macro_readers> g_macro_readers;
macro_readers & get_macro_readers() {
    if (!g_macro_readers)
        g_macro_readers.reset(new macro_readers());
    return *(g_macro_readers.get());
}

void register_macro_deserializer(std::string const & k, macro_definition_cell::reader rd) {
    macro_readers & readers = get_macro_readers();
    lean_assert(readers.find(k) == readers.end());
    readers[k] = rd;
}

static expr read_macro_definition(deserializer & d, unsigned num, expr const * args) {
    auto k  = d.read_string();
    macro_readers & readers = get_macro_readers();
    auto it = readers.find(k);
    lean_assert(it != readers.end());
    return it->second(d, num, args);
}

serializer & operator<<(serializer & s, binder_info const & i) {
    s.write_bool(i.is_implicit());
    s.write_bool(i.is_cast());
    s.write_bool(i.is_contextual());
    s.write_bool(i.is_strict_implicit());
    return s;
}

static binder_info read_binder_info(deserializer & d) {
    bool imp   = d.read_bool();
    bool cast  = d.read_bool();
    bool ctx   = d.read_bool();
    bool s_imp = d.read_bool();
    return binder_info(imp, cast, ctx, s_imp);
}

class expr_serializer : public object_serializer<expr, expr_hash_alloc, expr_eqp> {
    typedef object_serializer<expr, expr_hash_alloc, expr_eqp> super;
    max_sharing_fn m_max_sharing_fn;

    void write_core(expr const & a) {
        auto k = a.kind();
        super::write_core(a, static_cast<char>(k), [&]() {
                serializer & s = get_owner();
                switch (k) {
                case expr_kind::Var:
                    s << var_idx(a);
                    break;
                case expr_kind::Constant:
                    s << const_name(a) << const_levels(a);
                    break;
                case expr_kind::Sort:
                    s << sort_level(a);
                    break;
                case expr_kind::Macro:
                    s << macro_num_args(a);
                    for (unsigned i = 0; i < macro_num_args(a); i++) {
                        write_core(macro_arg(a, i));
                    }
                    macro_def(a).write(s);
                    break;
                case expr_kind::App:
                    write_core(app_fn(a)); write_core(app_arg(a));
                    break;
                case expr_kind::Lambda: case expr_kind::Pi:
                    s << binding_name(a) << binding_info(a); write_core(binding_domain(a)); write_core(binding_body(a));
                    break;
                case expr_kind::Meta:
                    s << mlocal_name(a); write_core(mlocal_type(a));
                    break;
                case expr_kind::Local:
                    s << mlocal_name(a) << local_pp_name(a) << local_info(a); write_core(mlocal_type(a));
                    break;
                }
            });
    }
public:
    void write(expr const & a) {
        write_core(m_max_sharing_fn(a));
    }
};

class expr_deserializer : public object_deserializer<expr> {
    typedef object_deserializer<expr> super;
public:
    expr read_binding(expr_kind k) {
        deserializer & d   = get_owner();
        name n             = read_name(d);
        binder_info i      = read_binder_info(d);
        expr t             = read();
        return mk_binding(k, n, t, read(), i);
    }

    expr read() {
        return super::read_core([&](char c) {
                deserializer & d = get_owner();
                auto k = static_cast<expr_kind>(c);
                switch (k) {
                case expr_kind::Var:
                    return mk_var(d.read_unsigned());
                case expr_kind::Constant: {
                    auto n = read_name(d);
                    return mk_constant(n, read_levels(d));
                }
                case expr_kind::Sort:
                    return mk_sort(read_level(d));
                case expr_kind::Macro: {
                    unsigned n = d.read_unsigned();
                    buffer<expr> args;
                    for (unsigned i = 0; i < n; i++) {
                        args.push_back(read());
                    }
                    return read_macro_definition(d, args.size(), args.data());
                }
                case expr_kind::App: {
                    expr f = read();
                    return mk_app(f, read());
                }
                case expr_kind::Lambda: case expr_kind::Pi:
                    return read_binding(k);
                case expr_kind::Meta: {
                    name n = read_name(d);
                    return mk_metavar(n, read());
                }
                case expr_kind::Local: {
                    name n         = read_name(d);
                    name pp_n      = read_name(d);
                    binder_info bi = read_binder_info(d);
                    return mk_local(n, pp_n, read(), bi);
                }}
                throw_corrupted_file(); // LCOV_EXCL_LINE
            });
    }
};

struct expr_sd {
    unsigned m_s_extid;
    unsigned m_d_extid;
    expr_sd() {
        m_s_extid = serializer::register_extension([](){ return std::unique_ptr<serializer::extension>(new expr_serializer()); });
        m_d_extid = deserializer::register_extension([](){ return std::unique_ptr<deserializer::extension>(new expr_deserializer()); });
    }
};
static expr_sd g_expr_sd;

serializer & operator<<(serializer & s, expr const & n) {
    s.get_extension<expr_serializer>(g_expr_sd.m_s_extid).write(n);
    return s;
}

expr read_expr(deserializer & d) {
    return d.get_extension<expr_deserializer>(g_expr_sd.m_d_extid).read();
}

// Declaration serialization
static serializer & operator<<(serializer & s, level_param_names const & ps) { return write_list<name>(s, ps); }
static level_param_names read_level_params(deserializer & d) { return read_list<name>(d); }
serializer & operator<<(serializer & s, declaration const & d) {
    char k = 0;
    if (d.is_definition()) {
        k |= 1;
        if (d.is_opaque())
            k |= 2;
        if (d.use_conv_opt())
            k |= 4;
    }
    if (d.is_theorem() || d.is_axiom())
        k |= 8;
    s << k << d.get_name() << d.get_univ_params() << d.get_type();
    if (d.is_definition()) {
        s << d.get_value();
        if (!d.is_theorem())
            s << d.get_weight();
    }
    return s;
}

declaration read_declaration(deserializer & d, module_idx midx) {
    char k               = d.read_char();
    bool has_value       = (k & 1) != 0;
    bool is_th_ax        = (k & 8) != 0;
    name n               = read_name(d);
    level_param_names ps = read_level_params(d);
    expr t               = read_expr(d);
    if (has_value) {
        expr v      = read_expr(d);
        if (is_th_ax) {
            return mk_theorem(n, ps, t, v, midx);
        } else {
            unsigned w        = d.read_unsigned();
            bool is_opaque    = (k & 2) != 0;
            bool use_conv_opt = (k & 4) != 0;
            return mk_definition(n, ps, t, v, is_opaque, w, midx, use_conv_opt);
        }
    } else {
        if (is_th_ax)
            return mk_axiom(n, ps, t);
        else
            return mk_var_decl(n, ps, t);
    }
}

using inductive::inductive_decl;
using inductive::intro_rule;
using inductive::inductive_decl_name;
using inductive::inductive_decl_type;
using inductive::inductive_decl_intros;
using inductive::intro_rule_name;
using inductive::intro_rule_type;

serializer & operator<<(serializer & s, inductive_decls const & ds) {
    s << std::get<0>(ds) << std::get<1>(ds);
    auto const & ls = std::get<2>(ds);
    s << length(ls);
    for (inductive_decl const & d : ls) {
        s << inductive_decl_name(d) << inductive_decl_type(d) << length(inductive_decl_intros(d));
        for (intro_rule const & r : inductive_decl_intros(d))
            s << intro_rule_name(r) << intro_rule_type(r);
    }
    return s;
}

inductive_decls read_inductive_decls(deserializer & d) {
    level_param_names ps = read_level_params(d);
    unsigned num_params, num_decls;
    d >> num_params >> num_decls;
    buffer<inductive_decl> decls;
    for (unsigned i = 0; i < num_decls; i++) {
        name d_name = read_name(d);
        expr d_type = read_expr(d);
        unsigned num_intros = d.read_unsigned();
        buffer<intro_rule> rules;
        for (unsigned j = 0; j < num_intros; j++) {
            name r_name = read_name(d);
            expr r_type = read_expr(d);
            rules.push_back(intro_rule(r_name, r_type));
        }
        decls.push_back(inductive_decl(d_name, d_type, to_list(rules.begin(), rules.end())));
    }
    return inductive_decls(ps, num_params, to_list(decls.begin(), decls.end()));
}

static register_macro_deserializer_fn
let_macro_des_fn(get_let_macro_opcode(),
                 [](deserializer &, unsigned num, expr const * args) {
                     if (num != 1)
                         throw_corrupted_file();
                     return mk_let_macro(args[0]);
                 });
}
<commit_msg>fix(library/kernel_serializer): make sure temporary (internal) binder names do not leak into .olean files<commit_after>/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <string>
#include "util/object_serializer.h"
#include "kernel/expr.h"
#include "kernel/declaration.h"
#include "library/max_sharing.h"
#include "library/kernel_serializer.h"

// Procedures for serializing and deserializing kernel objects (levels, exprs, declarations)
namespace lean {
// Universe level serialization
class level_serializer : public object_serializer<level, level::ptr_hash, level::ptr_eq> {
    typedef object_serializer<level, level::ptr_hash, level::ptr_eq> super;
public:
    void write(level const & l) {
        super::write(l, [&]() {
                serializer & s = get_owner();
                auto k = kind(l);
                s << static_cast<char>(k);
                switch (k) {
                case level_kind::Zero:     break;
                case level_kind::Param:    s << param_id(l);   break;
                case level_kind::Global:   s << global_id(l);  break;
                case level_kind::Meta:     s << meta_id(l);    break;
                case level_kind::Max:      write(max_lhs(l));  write(max_rhs(l)); break;
                case level_kind::IMax:     write(imax_lhs(l)); write(imax_rhs(l)); break;
                case level_kind::Succ:     write(succ_of(l));  break;
                }
            });
    }
};

class level_deserializer : public object_deserializer<level> {
    typedef object_deserializer<level> super;
public:
    level read() {
        return super::read([&]() -> level {
                deserializer & d = get_owner();
                auto k = static_cast<level_kind>(d.read_char());
                switch (k) {
                case level_kind::Zero:
                    return mk_level_zero();
                case level_kind::Param:
                    return mk_param_univ(read_name(d));
                case level_kind::Global:
                    return mk_global_univ(read_name(d));
                case level_kind::Meta:
                    return mk_meta_univ(read_name(d));
                case level_kind::Max: {
                    level lhs = read();
                    return mk_max(lhs, read());
                }
                case level_kind::IMax: {
                    level lhs = read();
                    return mk_imax(lhs, read());
                }
                case level_kind::Succ:
                    return mk_succ(read());
                }
                throw_corrupted_file();
            });
    }
};

struct level_sd {
    unsigned m_s_extid;
    unsigned m_d_extid;
    level_sd() {
        m_s_extid = serializer::register_extension([](){
                return std::unique_ptr<serializer::extension>(new level_serializer());
            });
        m_d_extid = deserializer::register_extension([](){
                return std::unique_ptr<deserializer::extension>(new level_deserializer());
            });
    }
};

static level_sd g_level_sd;

serializer & operator<<(serializer & s, level const & n) {
    s.get_extension<level_serializer>(g_level_sd.m_s_extid).write(n);
    return s;
}

level read_level(deserializer & d) { return d.get_extension<level_deserializer>(g_level_sd.m_d_extid).read(); }

serializer & operator<<(serializer & s, levels const & ls) { return write_list<level>(s, ls); }

levels read_levels(deserializer & d) { return read_list<level>(d, read_level); }

// Expression serialization
typedef std::unordered_map<std::string, macro_definition_cell::reader> macro_readers;
static std::unique_ptr<macro_readers> g_macro_readers;
macro_readers & get_macro_readers() {
    if (!g_macro_readers)
        g_macro_readers.reset(new macro_readers());
    return *(g_macro_readers.get());
}

void register_macro_deserializer(std::string const & k, macro_definition_cell::reader rd) {
    macro_readers & readers = get_macro_readers();
    lean_assert(readers.find(k) == readers.end());
    readers[k] = rd;
}

static expr read_macro_definition(deserializer & d, unsigned num, expr const * args) {
    auto k  = d.read_string();
    macro_readers & readers = get_macro_readers();
    auto it = readers.find(k);
    lean_assert(it != readers.end());
    return it->second(d, num, args);
}

serializer & operator<<(serializer & s, binder_info const & i) {
    s.write_bool(i.is_implicit());
    s.write_bool(i.is_cast());
    s.write_bool(i.is_contextual());
    s.write_bool(i.is_strict_implicit());
    return s;
}

static binder_info read_binder_info(deserializer & d) {
    bool imp   = d.read_bool();
    bool cast  = d.read_bool();
    bool ctx   = d.read_bool();
    bool s_imp = d.read_bool();
    return binder_info(imp, cast, ctx, s_imp);
}

static name g_binder_name("a");

class expr_serializer : public object_serializer<expr, expr_hash_alloc, expr_eqp> {
    typedef object_serializer<expr, expr_hash_alloc, expr_eqp> super;
    max_sharing_fn m_max_sharing_fn;
    unsigned       m_next_id;

    void write_binder_name(serializer & s, name const & a) {
        // make sure binding names are atomic string
        if (!a.is_atomic() || a.is_numeral()) {
            s << g_binder_name.append_after(m_next_id);
            m_next_id++;
        } else {
            s << a;
        }
    }

    void write_core(expr const & a) {
        auto k = a.kind();
        super::write_core(a, static_cast<char>(k), [&]() {
                serializer & s = get_owner();
                switch (k) {
                case expr_kind::Var:
                    s << var_idx(a);
                    break;
                case expr_kind::Constant:
                    s << const_name(a) << const_levels(a);
                    break;
                case expr_kind::Sort:
                    s << sort_level(a);
                    break;
                case expr_kind::Macro:
                    s << macro_num_args(a);
                    for (unsigned i = 0; i < macro_num_args(a); i++) {
                        write_core(macro_arg(a, i));
                    }
                    macro_def(a).write(s);
                    break;
                case expr_kind::App:
                    write_core(app_fn(a)); write_core(app_arg(a));
                    break;
                case expr_kind::Lambda: case expr_kind::Pi:
                    write_binder_name(s, binding_name(a));
                    s << binding_info(a); write_core(binding_domain(a)); write_core(binding_body(a));
                    break;
                case expr_kind::Meta:
                    s << mlocal_name(a); write_core(mlocal_type(a));
                    break;
                case expr_kind::Local:
                    s << mlocal_name(a) << local_pp_name(a) << local_info(a); write_core(mlocal_type(a));
                    break;
                }
            });
    }
public:
    expr_serializer() { m_next_id = 0; }
    void write(expr const & a) {
        write_core(m_max_sharing_fn(a));
    }
};

class expr_deserializer : public object_deserializer<expr> {
    typedef object_deserializer<expr> super;
public:
    expr read_binding(expr_kind k) {
        deserializer & d   = get_owner();
        name n             = read_name(d);
        binder_info i      = read_binder_info(d);
        expr t             = read();
        return mk_binding(k, n, t, read(), i);
    }

    expr read() {
        return super::read_core([&](char c) {
                deserializer & d = get_owner();
                auto k = static_cast<expr_kind>(c);
                switch (k) {
                case expr_kind::Var:
                    return mk_var(d.read_unsigned());
                case expr_kind::Constant: {
                    auto n = read_name(d);
                    return mk_constant(n, read_levels(d));
                }
                case expr_kind::Sort:
                    return mk_sort(read_level(d));
                case expr_kind::Macro: {
                    unsigned n = d.read_unsigned();
                    buffer<expr> args;
                    for (unsigned i = 0; i < n; i++) {
                        args.push_back(read());
                    }
                    return read_macro_definition(d, args.size(), args.data());
                }
                case expr_kind::App: {
                    expr f = read();
                    return mk_app(f, read());
                }
                case expr_kind::Lambda: case expr_kind::Pi:
                    return read_binding(k);
                case expr_kind::Meta: {
                    name n = read_name(d);
                    return mk_metavar(n, read());
                }
                case expr_kind::Local: {
                    name n         = read_name(d);
                    name pp_n      = read_name(d);
                    binder_info bi = read_binder_info(d);
                    return mk_local(n, pp_n, read(), bi);
                }}
                throw_corrupted_file(); // LCOV_EXCL_LINE
            });
    }
};

struct expr_sd {
    unsigned m_s_extid;
    unsigned m_d_extid;
    expr_sd() {
        m_s_extid = serializer::register_extension([](){ return std::unique_ptr<serializer::extension>(new expr_serializer()); });
        m_d_extid = deserializer::register_extension([](){ return std::unique_ptr<deserializer::extension>(new expr_deserializer()); });
    }
};
static expr_sd g_expr_sd;

serializer & operator<<(serializer & s, expr const & n) {
    s.get_extension<expr_serializer>(g_expr_sd.m_s_extid).write(n);
    return s;
}

expr read_expr(deserializer & d) {
    return d.get_extension<expr_deserializer>(g_expr_sd.m_d_extid).read();
}

// Declaration serialization
static serializer & operator<<(serializer & s, level_param_names const & ps) { return write_list<name>(s, ps); }
static level_param_names read_level_params(deserializer & d) { return read_list<name>(d); }
serializer & operator<<(serializer & s, declaration const & d) {
    char k = 0;
    if (d.is_definition()) {
        k |= 1;
        if (d.is_opaque())
            k |= 2;
        if (d.use_conv_opt())
            k |= 4;
    }
    if (d.is_theorem() || d.is_axiom())
        k |= 8;
    s << k << d.get_name() << d.get_univ_params() << d.get_type();
    if (d.is_definition()) {
        s << d.get_value();
        if (!d.is_theorem())
            s << d.get_weight();
    }
    return s;
}

declaration read_declaration(deserializer & d, module_idx midx) {
    char k               = d.read_char();
    bool has_value       = (k & 1) != 0;
    bool is_th_ax        = (k & 8) != 0;
    name n               = read_name(d);
    level_param_names ps = read_level_params(d);
    expr t               = read_expr(d);
    if (has_value) {
        expr v      = read_expr(d);
        if (is_th_ax) {
            return mk_theorem(n, ps, t, v, midx);
        } else {
            unsigned w        = d.read_unsigned();
            bool is_opaque    = (k & 2) != 0;
            bool use_conv_opt = (k & 4) != 0;
            return mk_definition(n, ps, t, v, is_opaque, w, midx, use_conv_opt);
        }
    } else {
        if (is_th_ax)
            return mk_axiom(n, ps, t);
        else
            return mk_var_decl(n, ps, t);
    }
}

using inductive::inductive_decl;
using inductive::intro_rule;
using inductive::inductive_decl_name;
using inductive::inductive_decl_type;
using inductive::inductive_decl_intros;
using inductive::intro_rule_name;
using inductive::intro_rule_type;

serializer & operator<<(serializer & s, inductive_decls const & ds) {
    s << std::get<0>(ds) << std::get<1>(ds);
    auto const & ls = std::get<2>(ds);
    s << length(ls);
    for (inductive_decl const & d : ls) {
        s << inductive_decl_name(d) << inductive_decl_type(d) << length(inductive_decl_intros(d));
        for (intro_rule const & r : inductive_decl_intros(d))
            s << intro_rule_name(r) << intro_rule_type(r);
    }
    return s;
}

inductive_decls read_inductive_decls(deserializer & d) {
    level_param_names ps = read_level_params(d);
    unsigned num_params, num_decls;
    d >> num_params >> num_decls;
    buffer<inductive_decl> decls;
    for (unsigned i = 0; i < num_decls; i++) {
        name d_name = read_name(d);
        expr d_type = read_expr(d);
        unsigned num_intros = d.read_unsigned();
        buffer<intro_rule> rules;
        for (unsigned j = 0; j < num_intros; j++) {
            name r_name = read_name(d);
            expr r_type = read_expr(d);
            rules.push_back(intro_rule(r_name, r_type));
        }
        decls.push_back(inductive_decl(d_name, d_type, to_list(rules.begin(), rules.end())));
    }
    return inductive_decls(ps, num_params, to_list(decls.begin(), decls.end()));
}

static register_macro_deserializer_fn
let_macro_des_fn(get_let_macro_opcode(),
                 [](deserializer &, unsigned num, expr const * args) {
                     if (num != 1)
                         throw_corrupted_file();
                     return mk_let_macro(args[0]);
                 });
}
<|endoftext|>


<commit_before>namespace factor
{

#if defined(FACTOR_X86)
  extern "C" __attribute__ ((regparm (1))) typedef void (*primitive_type)(void *myvm);
  #define PRIMITIVE(name) extern "C" __attribute__ ((regparm (1)))  void primitive_##name(void *myvm)
  #define PRIMITIVE_GETVM() ((factorvm*)myvm)
#else
  extern "C" typedef void (*primitive_type)(void *myvm);
  #define PRIMITIVE(name) extern "C" void primitive_##name(void *myvm)
  #define PRIMITIVE_GETVM() vm
#endif

extern const primitive_type primitives[];
#define PRIMITIVE_OVERFLOW_GETVM() vm

#define VM_PTR vm
#define ASSERTVM()
}
<commit_msg>overflow functions now retrieving their vm ptr from above ds stack<commit_after>namespace factor
{

#if defined(FACTOR_X86)
  extern "C" __attribute__ ((regparm (1))) typedef void (*primitive_type)(void *myvm);
  #define PRIMITIVE(name) extern "C" __attribute__ ((regparm (1)))  void primitive_##name(void *myvm)
  #define PRIMITIVE_GETVM() ((factorvm*)myvm)
#else
  extern "C" typedef void (*primitive_type)(void *myvm);
  #define PRIMITIVE(name) extern "C" void primitive_##name(void *myvm)
  #define PRIMITIVE_GETVM() vm
#endif

extern const primitive_type primitives[];
#define PRIMITIVE_OVERFLOW_GETVM() vm
#define VM_PTR vm
#define ASSERTVM()
}
<|endoftext|>


<commit_before>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Touchable.cpp
 *  @brief  EC_Touchable enables visual effect for scene entity in cases where
 *          the entity can be considered to have some kind of functionality
 *          when it is clicked i.e. touched. The effect is not visible by default.
 *          You must call Show() function separately. The effect is visible only
 *          for certain time.
 *  @note   The entity must have EC_OgrePlaceable and EC_OgreMesh (if mesh) or
 *          EC_OgreCustomObject (if prim) components available in advance.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_Touchable.h"

#include "IModule.h"
#include "Entity.h"
#include "Renderer.h"
//#include "OgreMaterialUtils.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EC_OgreCustomObject.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Touchable");

#include <QApplication>
#include <QTimer>

#include "MemoryLeakCheck.h"

EC_Touchable::~EC_Touchable()
{
    // OgreRendering module might be already deleted. If so, the cloned entity is also already deleted.
    // In this case, just set pointer to 0.
    if (!renderer_.expired())
    {
        Ogre::SceneManager *sceneMgr = renderer_.lock()->GetSceneManager();
        if (entityClone_)
            sceneMgr->destroyEntity(entityClone_);
    }
    else
    {
        entityClone_ = 0;
        sceneNode_ = 0;
    }
}

void EC_Touchable::Show()
{
    if (highlightOnHover.Get())
    {
        if (!entityClone_)
            Create();

        if (!entityClone_)
        {
            LogError("EC_Touchable not initialized properly.");
            return;
        }

        if (entityClone_ && sceneNode_)
            sceneNode_->getAttachedObject(cloneName_)->setVisible(true);
    }
}

void EC_Touchable::Hide()
{
    if (entityClone_ && sceneNode_)
        sceneNode_->getAttachedObject(cloneName_)->setVisible(false);
}

bool EC_Touchable::IsVisible() const
{
    if (entityClone_ && sceneNode_)
        return sceneNode_->getAttachedObject(cloneName_)->isVisible();
    return false;
}

EC_Touchable::EC_Touchable(IModule *module) :
    IComponent(module->GetFramework()),
    entityClone_(0),
    sceneNode_(0),
    materialName(this, "material name", "Touchable"),
    highlightOnHover(this, "highligh on hover", true),
    hoverCursor(this, "hover cursor", Qt::ArrowCursor)
{
    static AttributeMetadata metadata;
    static bool metadataInitialized = false;
    if(!metadataInitialized)
    {
        metadata.enums[Qt::ArrowCursor] = "ArrowCursor";
        metadata.enums[Qt::UpArrow] = "UpArrowCursor";
        metadata.enums[Qt::CrossCursor] = "CrossCursor";
        metadata.enums[Qt::WaitCursor] = "WaitCursor";
        metadata.enums[Qt::IBeamCursor] = "IBeamCursor";
        metadata.enums[Qt::SizeVerCursor] = "SizeVerCursor";
        metadata.enums[Qt::SizeHorCursor] = "SizeHorCursor";
        metadata.enums[Qt::SizeBDiagCursor] = "SizeBDiagCursor";
        metadata.enums[Qt::SizeFDiagCursor] = "SizeFDiagCursor";
        metadata.enums[Qt::SizeAllCursor] = "SizeAllCursor";
        metadata.enums[Qt::BlankCursor] = "BlankCursor";
        metadata.enums[Qt::SplitVCursor] = "SplitVCursor";
        metadata.enums[Qt::SplitHCursor] = "SplitHCursor";
        metadata.enums[Qt::PointingHandCursor] = "PointingHandCursor";
        metadata.enums[Qt::ForbiddenCursor] = "ForbiddenCursor";
        metadata.enums[Qt::WhatsThisCursor] = "WhatsThisCursor";
        metadata.enums[Qt::BusyCursor] = "BusyCursor";
        metadata.enums[Qt::OpenHandCursor] = "OpenHandCursor";
        metadata.enums[Qt::ClosedHandCursor] = "ClosedHandCursor";
        metadataInitialized = true;
    }

    hoverCursor.SetMetadata(&metadata);

    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);
    connect(this, SIGNAL(OnChanged()), SLOT(UpdateMaterial()));
    connect(this, SIGNAL(ParentEntitySet()), SLOT(RegisterActions()));
//    connect(this, SIGNAL(ParentEntitySet()), SLOT(Create()));
}

void EC_Touchable::Create()
{
    if (renderer_.expired())
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *placeable = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    assert(placeable);
    if (!placeable)
        return;

    // Check out if this entity has EC_OgreMesh or EC_OgreCustomObject.
    Ogre::Entity *originalEntity  = 0;
    if (entity->GetComponent(OgreRenderer::EC_OgreMesh::TypeNameStatic()))
    {
        OgreRenderer::EC_OgreMesh *ec_mesh= entity->GetComponent<OgreRenderer::EC_OgreMesh>().get();
        assert(ec_mesh);

        originalEntity = ec_mesh->GetEntity();
        sceneNode_ = ec_mesh->GetAdjustmentSceneNode();
    }
    else if(entity->GetComponent(OgreRenderer::EC_OgreCustomObject::TypeNameStatic()))
    {
        OgreRenderer::EC_OgreCustomObject *ec_custom = entity->GetComponent<OgreRenderer::EC_OgreCustomObject>().get();
        assert(ec_custom);
        if (!ec_custom->IsCommitted())
        {
            LogError("Mesh entity have not been created for the target primitive. Cannot create EC_Touchable.");
            return;
        }

        originalEntity = ec_custom->GetEntity();
        sceneNode_ = placeable->GetSceneNode();
    }
    else
    {
        LogError("This entity doesn't have either EC_OgreMesh or EC_OgreCustomObject present. Cannot create EC_Touchable.");
        return;
    }

    assert(originalEntity && sceneNode_);
    if (!originalEntity || !sceneNode_)
        return;

    // Clone the Ogre entity.
    cloneName_ = std::string("entity") + renderer_.lock()->GetUniqueObjectName();
    entityClone_ = originalEntity->clone(cloneName_);
    assert(entityClone_);

    // Disable casting of shadows for the clone.
    entityClone_->setCastShadows(false);

    ///\todo If original entity has skeleton, (try to) link it to the clone.
/*
    if (originalEntity->hasSkeleton())
    {
        Ogre::SkeletonInstance *skel = originalEntity->getSkeleton();
        // If sharing a skeleton, force the attachment mesh to use the same skeleton
        // This is theoretically quite a scary operation, for there is possibility for things to go wrong
        Ogre::SkeletonPtr entity_skel = originalEntity->getMesh()->getSkeleton();
        if (entity_skel.isNull())
        {
            LogError("Cannot share skeleton for attachment, not found");
        }
        else
        {
            try
            {
                entityClone_->getMesh()->_notifySkeleton(entity_skel);
            }
            catch (Ogre::Exception &e)
            {
                LogError("Could not set shared skeleton for attachment: " + std::string(e.what()));
            }
        }
    }
*/

    try
    {
        //OgreRenderer::CloneMaterial("Touchable", materialName.Get());
        entityClone_->setMaterialName(materialName.Get().toStdString());
    }
    catch (Ogre::Exception &e)
    {
        LogError("Could not set material \"" + materialName.Get().toStdString() + "\": " + std::string(e.what()));
        return;
    }

    sceneNode_->attachObject(entityClone_);
    Hide();
}

void EC_Touchable::UpdateMaterial()
{
    if (!entityClone_ ||!sceneNode_)
        return;
    try
    {
        entityClone_->setMaterialName(materialName.Get().toStdString());
    }
    catch (Ogre::Exception &e)
    {
        LogError("Could not set material \"" + materialName.Get().toStdString() + "\": " + std::string(e.what()));
        return;
    }

//    hover_cursor_ = QCursor((Qt::CursorShape)(hoverCursor.Get()));
}

///\todo Remove this altogether. -jj. Integrate switching mouse cursors to input contexts so that
/// it is not possible to "miss" calling restoreOverrideCursor and leak a cursor to stay on screen. Releasing a context
/// also releases the cursor.
void EC_Touchable::SetCursorVisible(bool visible)
{
    if (hoverCursor.Get() != Qt::ArrowCursor)
    {
        QCursor *current_cursor = QApplication::overrideCursor();
        if (visible)
        {
            if (current_cursor)
            {
                if (current_cursor->shape() != hoverCursor.Get())
                    QApplication::setOverrideCursor(QCursor((Qt::CursorShape)(hoverCursor.Get())));
            }
            else
                QApplication::setOverrideCursor(QCursor((Qt::CursorShape)(hoverCursor.Get())));
        }
        else
        {
            while (current_cursor)
            {
                QApplication::restoreOverrideCursor();
                current_cursor = QApplication::overrideCursor();
            }
        }
    }
}

void EC_Touchable::OnHoverIn()
{
    LogInfo("OnHoverIn");
    SetCursorVisible(true);
    emit MouseHoverIn();
}

void EC_Touchable::OnHover()
{
    LogInfo("OnHover");
    if (!IsVisible())
        Show();
    emit MouseHover();
}

void EC_Touchable::OnHoverOut()
{
    LogInfo("OnHoverOut");
    if (IsVisible())
        Hide();

    SetCursorVisible(false);
    emit MouseHoverOut();
}

void EC_Touchable::OnClick()
{
    LogInfo("OnClick");
    emit MousePressed();
}

void EC_Touchable::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
    {
        // Generic actions
        entity->ConnectAction("Show", this, SLOT(Show()));
        entity->ConnectAction("Hide", this, SLOT(Hide()));
        // Mouse actions
        entity->ConnectAction("MouseHover", this, SLOT(OnHover()));
        entity->ConnectAction("MouseHoverIn", this, SLOT(OnHoverIn()));
        entity->ConnectAction("MouseHoverOut", this, SLOT(OnHoverOut()));
        entity->ConnectAction("MousePress", this, SLOT(OnClick()));
    }
}

<commit_msg>Remove debug prints.<commit_after>/**
 *  For conditions of distribution and use, see copyright notice in license.txt
 *
 *  @file   EC_Touchable.cpp
 *  @brief  EC_Touchable enables visual effect for scene entity in cases where
 *          the entity can be considered to have some kind of functionality
 *          when it is clicked i.e. touched. The effect is not visible by default.
 *          You must call Show() function separately. The effect is visible only
 *          for certain time.
 *  @note   The entity must have EC_OgrePlaceable and EC_OgreMesh (if mesh) or
 *          EC_OgreCustomObject (if prim) components available in advance.
 */

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_Touchable.h"

#include "IModule.h"
#include "Entity.h"
#include "Renderer.h"
//#include "OgreMaterialUtils.h"
#include "EC_OgrePlaceable.h"
#include "EC_OgreMesh.h"
#include "EC_OgreCustomObject.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_Touchable");

#include <QApplication>
#include <QTimer>

#include "MemoryLeakCheck.h"

EC_Touchable::~EC_Touchable()
{
    // OgreRendering module might be already deleted. If so, the cloned entity is also already deleted.
    // In this case, just set pointer to 0.
    if (!renderer_.expired())
    {
        Ogre::SceneManager *sceneMgr = renderer_.lock()->GetSceneManager();
        if (entityClone_)
            sceneMgr->destroyEntity(entityClone_);
    }
    else
    {
        entityClone_ = 0;
        sceneNode_ = 0;
    }
}

void EC_Touchable::Show()
{
    if (highlightOnHover.Get())
    {
        if (!entityClone_)
            Create();

        if (!entityClone_)
        {
            LogError("EC_Touchable not initialized properly.");
            return;
        }

        if (entityClone_ && sceneNode_)
            sceneNode_->getAttachedObject(cloneName_)->setVisible(true);
    }
}

void EC_Touchable::Hide()
{
    if (entityClone_ && sceneNode_)
        sceneNode_->getAttachedObject(cloneName_)->setVisible(false);
}

bool EC_Touchable::IsVisible() const
{
    if (entityClone_ && sceneNode_)
        return sceneNode_->getAttachedObject(cloneName_)->isVisible();
    return false;
}

EC_Touchable::EC_Touchable(IModule *module) :
    IComponent(module->GetFramework()),
    entityClone_(0),
    sceneNode_(0),
    materialName(this, "material name", "Touchable"),
    highlightOnHover(this, "highligh on hover", true),
    hoverCursor(this, "hover cursor", Qt::ArrowCursor)
{
    static AttributeMetadata metadata;
    static bool metadataInitialized = false;
    if(!metadataInitialized)
    {
        metadata.enums[Qt::ArrowCursor] = "ArrowCursor";
        metadata.enums[Qt::UpArrow] = "UpArrowCursor";
        metadata.enums[Qt::CrossCursor] = "CrossCursor";
        metadata.enums[Qt::WaitCursor] = "WaitCursor";
        metadata.enums[Qt::IBeamCursor] = "IBeamCursor";
        metadata.enums[Qt::SizeVerCursor] = "SizeVerCursor";
        metadata.enums[Qt::SizeHorCursor] = "SizeHorCursor";
        metadata.enums[Qt::SizeBDiagCursor] = "SizeBDiagCursor";
        metadata.enums[Qt::SizeFDiagCursor] = "SizeFDiagCursor";
        metadata.enums[Qt::SizeAllCursor] = "SizeAllCursor";
        metadata.enums[Qt::BlankCursor] = "BlankCursor";
        metadata.enums[Qt::SplitVCursor] = "SplitVCursor";
        metadata.enums[Qt::SplitHCursor] = "SplitHCursor";
        metadata.enums[Qt::PointingHandCursor] = "PointingHandCursor";
        metadata.enums[Qt::ForbiddenCursor] = "ForbiddenCursor";
        metadata.enums[Qt::WhatsThisCursor] = "WhatsThisCursor";
        metadata.enums[Qt::BusyCursor] = "BusyCursor";
        metadata.enums[Qt::OpenHandCursor] = "OpenHandCursor";
        metadata.enums[Qt::ClosedHandCursor] = "ClosedHandCursor";
        metadataInitialized = true;
    }

    hoverCursor.SetMetadata(&metadata);

    renderer_ = module->GetFramework()->GetServiceManager()->GetService<OgreRenderer::Renderer>(Foundation::Service::ST_Renderer);
    connect(this, SIGNAL(OnChanged()), SLOT(UpdateMaterial()));
    connect(this, SIGNAL(ParentEntitySet()), SLOT(RegisterActions()));
//    connect(this, SIGNAL(ParentEntitySet()), SLOT(Create()));
}

void EC_Touchable::Create()
{
    if (renderer_.expired())
        return;

    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (!entity)
        return;

    OgreRenderer::EC_OgrePlaceable *placeable = entity->GetComponent<OgreRenderer::EC_OgrePlaceable>().get();
    assert(placeable);
    if (!placeable)
        return;

    // Check out if this entity has EC_OgreMesh or EC_OgreCustomObject.
    Ogre::Entity *originalEntity  = 0;
    if (entity->GetComponent(OgreRenderer::EC_OgreMesh::TypeNameStatic()))
    {
        OgreRenderer::EC_OgreMesh *ec_mesh= entity->GetComponent<OgreRenderer::EC_OgreMesh>().get();
        assert(ec_mesh);

        originalEntity = ec_mesh->GetEntity();
        sceneNode_ = ec_mesh->GetAdjustmentSceneNode();
    }
    else if(entity->GetComponent(OgreRenderer::EC_OgreCustomObject::TypeNameStatic()))
    {
        OgreRenderer::EC_OgreCustomObject *ec_custom = entity->GetComponent<OgreRenderer::EC_OgreCustomObject>().get();
        assert(ec_custom);
        if (!ec_custom->IsCommitted())
        {
            LogError("Mesh entity have not been created for the target primitive. Cannot create EC_Touchable.");
            return;
        }

        originalEntity = ec_custom->GetEntity();
        sceneNode_ = placeable->GetSceneNode();
    }
    else
    {
        LogError("This entity doesn't have either EC_OgreMesh or EC_OgreCustomObject present. Cannot create EC_Touchable.");
        return;
    }

    assert(originalEntity && sceneNode_);
    if (!originalEntity || !sceneNode_)
        return;

    // Clone the Ogre entity.
    cloneName_ = std::string("entity") + renderer_.lock()->GetUniqueObjectName();
    entityClone_ = originalEntity->clone(cloneName_);
    assert(entityClone_);

    // Disable casting of shadows for the clone.
    entityClone_->setCastShadows(false);

    ///\todo If original entity has skeleton, (try to) link it to the clone.
/*
    if (originalEntity->hasSkeleton())
    {
        Ogre::SkeletonInstance *skel = originalEntity->getSkeleton();
        // If sharing a skeleton, force the attachment mesh to use the same skeleton
        // This is theoretically quite a scary operation, for there is possibility for things to go wrong
        Ogre::SkeletonPtr entity_skel = originalEntity->getMesh()->getSkeleton();
        if (entity_skel.isNull())
        {
            LogError("Cannot share skeleton for attachment, not found");
        }
        else
        {
            try
            {
                entityClone_->getMesh()->_notifySkeleton(entity_skel);
            }
            catch (Ogre::Exception &e)
            {
                LogError("Could not set shared skeleton for attachment: " + std::string(e.what()));
            }
        }
    }
*/

    try
    {
        //OgreRenderer::CloneMaterial("Touchable", materialName.Get());
        entityClone_->setMaterialName(materialName.Get().toStdString());
    }
    catch (Ogre::Exception &e)
    {
        LogError("Could not set material \"" + materialName.Get().toStdString() + "\": " + std::string(e.what()));
        return;
    }

    sceneNode_->attachObject(entityClone_);
    Hide();
}

void EC_Touchable::UpdateMaterial()
{
    if (!entityClone_ ||!sceneNode_)
        return;
    try
    {
        entityClone_->setMaterialName(materialName.Get().toStdString());
    }
    catch (Ogre::Exception &e)
    {
        LogError("Could not set material \"" + materialName.Get().toStdString() + "\": " + std::string(e.what()));
        return;
    }

//    hover_cursor_ = QCursor((Qt::CursorShape)(hoverCursor.Get()));
}

///\todo Remove this altogether. -jj. Integrate switching mouse cursors to input contexts so that
/// it is not possible to "miss" calling restoreOverrideCursor and leak a cursor to stay on screen. Releasing a context
/// also releases the cursor.
void EC_Touchable::SetCursorVisible(bool visible)
{
    if (hoverCursor.Get() != Qt::ArrowCursor)
    {
        QCursor *current_cursor = QApplication::overrideCursor();
        if (visible)
        {
            if (current_cursor)
            {
                if (current_cursor->shape() != hoverCursor.Get())
                    QApplication::setOverrideCursor(QCursor((Qt::CursorShape)(hoverCursor.Get())));
            }
            else
                QApplication::setOverrideCursor(QCursor((Qt::CursorShape)(hoverCursor.Get())));
        }
        else
        {
            while (current_cursor)
            {
                QApplication::restoreOverrideCursor();
                current_cursor = QApplication::overrideCursor();
            }
        }
    }
}

void EC_Touchable::OnHoverIn()
{
    SetCursorVisible(true);
    emit MouseHoverIn();
}

void EC_Touchable::OnHover()
{
    if (!IsVisible())
        Show();
    emit MouseHover();
}

void EC_Touchable::OnHoverOut()
{
    if (IsVisible())
        Hide();

    SetCursorVisible(false);
    emit MouseHoverOut();
}

void EC_Touchable::OnClick()
{
    emit MousePressed();
}

void EC_Touchable::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
    {
        // Generic actions
        entity->ConnectAction("Show", this, SLOT(Show()));
        entity->ConnectAction("Hide", this, SLOT(Hide()));
        // Mouse actions
        entity->ConnectAction("MouseHover", this, SLOT(OnHover()));
        entity->ConnectAction("MouseHoverIn", this, SLOT(OnHoverIn()));
        entity->ConnectAction("MouseHoverOut", this, SLOT(OnHoverOut()));
        entity->ConnectAction("MousePress", this, SLOT(OnClick()));
    }
}

<|endoftext|>