<commit_before>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/io/File.h"

#include "db/io/FileFunctions.h"
#include "db/io/FileList.h"
#include "db/io/IOException.h"
#include "db/rt/DynamicObject.h"
#include "db/util/StringTokenizer.h"

#include <cstdlib>
#include <cstring>
#include <cstdarg>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <vector>

using namespace std;
using namespace db::io;
using namespace db::rt;
using namespace db::util;

FileImpl::FileImpl()
{
   mName = strdup("");
}

FileImpl::FileImpl(const char* name)
{
   mName = strdup(name);
}

FileImpl::~FileImpl()
{
   free(mName);
}

bool FileImpl::create()
{
   bool rval = false;

   FILE* fp = fopen(mName, "w");
   if(fp != NULL)
   {
      rval = true;
      fclose(fp);
   }
   else
   {
      string msg = "Could not create file! ";
      msg.append(strerror(errno));
      ExceptionRef e = new IOException(msg.c_str());
      Exception::setLast(e, false);
   }

   return rval;
}

bool FileImpl::mkdirs()
{
   bool rval = true;

   // get path
   string path = (isDirectory() ? getName() : File::parentname(getName()));

   // create stack of directories
   vector<string> dirStack;
   dirStack.push_back(path);
   while(strcmp(path.c_str(), "/") != 0)
   {
      path = File::parentname(path.c_str());
      dirStack.push_back(path);
   }

   // iteratively create directories
   struct stat s;
   int rc;
   while(rval && !dirStack.empty())
   {
      path = dirStack.back();
      dirStack.pop_back();

      // try to stat directory
      rc = stat(path.c_str(), &s);
      if(rc != 0)
      {
         // Note: windows does not allow permissions in mkdir()
         // directory doesn't exist, so try to create it
         if(mkdir(path.c_str(), 0777) < 0)
         {
            string msg = "Could not make directory! ";
            msg.append(strerror(errno));
            ExceptionRef e = new IOException(msg.c_str());
            e->getDetails()["path"] = path.c_str();
            Exception::setLast(e, false);
            rval = false;
         }
      }
   }

   return rval;
}

bool FileImpl::exists()
{
   bool rval = false;

   struct stat s;
   int rc = stat(mName, &s);
   if(rc == 0)
   {
      rval = true;
   }
   else
   {
      // does not set an exception intentionally
   }

   return rval;
}

bool FileImpl::remove()
{
   bool rval = false;

   int rc = ::remove(mName);
   if(rc == 0)
   {
      rval = true;
   }
   else
   {
      // FIXME: want to make sure no exception is
      // set when the file didn't exist prior to deletion
//      string msg = "Could not delete file! ";
//      msg.append(strerror(errno));
//      ExceptionRef e = new IOException(msg.c_str());
//      Exception::setLast(e, false);
   }

   return rval;
}

bool FileImpl::rename(File& file)
{
   bool rval = false;

   // delete old file
   file->remove();

   // rename file
   int rc = ::rename(mName, file->getName());
   if(rc == 0)
   {
      rval = true;
   }
   else
   {
      string msg = "Could not rename file! ";
      msg.append(strerror(errno));
      ExceptionRef e = new IOException(msg.c_str());
      Exception::setLast(e, false);
   }

   return rval;
}

const char* FileImpl::getName() const
{
   return mName;
}

off_t FileImpl::getLength()
{
   struct stat s;
   int rc = stat(mName, &s);
   if(rc != 0)
   {
      string msg = "Could not stat file! ";
      msg.append(strerror(errno));
      ExceptionRef e = new IOException(msg.c_str());
      Exception::setLast(e, false);
   }

   return s.st_size;
}

FileImpl::Type FileImpl::getType()
{
   Type rval = Unknown;

   // use lstat so symbolic links aren't followed
   struct stat s;
   int rc = stat(mName, &s);
   if(rc != 0)
   {
   }
   else
   {
      switch(s.st_mode & S_IFMT)
      {
         case S_IFREG:
            rval = RegularFile;
            break;
         case S_IFDIR:
            rval = Directory;
            break;
         case S_IFLNK:
            rval = SymbolicLink;
            break;
         default:
            break;
      }
   }

   return rval;
}

bool FileImpl::isFile()
{
   return getType() == RegularFile;
}

bool FileImpl::contains(const char* path)
{
   bool rval = false;
   string normalizedContainer;
   string normalizedFileImpl;

   if(File::normalizePath(getName(), normalizedContainer) &&
      File::normalizePath(path, normalizedFileImpl))
   {
      rval = (normalizedFileImpl.find(normalizedContainer, 0) == 0);
   }

   return rval;
}

bool FileImpl::contains(File& path)
{
   return contains(path->getName());
}

bool FileImpl::isDirectory()
{
   return getType() == Directory;
}

bool FileImpl::isReadable()
{
   bool rval = false;
   string npath;

   if(File::normalizePath(getName(), npath))
   {
      rval = File::isPathReadable(npath.c_str());
   }

   return rval;
}

bool FileImpl::isSymbolicLink()
{
   return getType() == SymbolicLink;
}

bool FileImpl::isWritable()
{
   bool rval = false;
   string npath;

   if(File::normalizePath(getName(), npath))
   {
      rval = File::isPathWritable(npath.c_str());
   }

   return rval;
}

void FileImpl::listFiles(FileList& files)
{
   if(isDirectory())
   {
      // open directory
      DIR* dir = opendir(mName);
      if(dir == NULL)
      {
         // FIXME: add error handling
      }
      else
      {
         // read each directory entry
         struct dirent* entry;
         unsigned int len1 = strlen(mName);
         bool separator = mName[len1 - 1] != '/';
         while((entry = readdir(dir)) != NULL)
         {
            // d_name is null-terminated name for FileImpl, without path name
            // so copy FileImpl name before d_name to get full path
            unsigned int len2 = strlen(entry->d_name);
            char path[len1 + len2 + 2];
            memcpy(path, mName, len1);
            if(separator)
            {
               // add path separator as appropriate
               path[len1] = '/';
               memcpy(path + len1 + 1, entry->d_name, len2 + 1);
            }
            else
            {
               memcpy(path + len1, entry->d_name, len2 + 1);
            }

            // add new FileImpl to list
            File file(path);
            files->add(file);
         }

         // close directory
         closedir(dir);
      }
   }
}

Date FileImpl::getModifiedDate()
{
   Date date(0);
   struct stat s;

   if(stat(mName, &s) == 0)
   {
      date.setSeconds(s.st_mtime);
   }

   return date;
}

bool File::operator==(const File& rhs) const
{
   bool rval = false;

   File& file = *((File*)&rhs);

   // compare names and types for equality
   if(strcmp((*this)->getName(), file->getName()) == 0)
   {
      rval = ((*this)->getType() == file->getType());
   }

   return rval;
}

bool File::normalizePath(const char* path, string& normalizedPath)
{
   bool rval = true;
   string tempPath;

   if(strlen(path) > 0)
   {
      // if the path isn't absolute, pre-pend the current working directory
      // to the path.
      if(path[0] != '/')
      {
         rval = getCurrentWorkingDirectory(tempPath);

         tempPath.push_back('/');
         tempPath.append(path);
      }
      else
      {
         tempPath.append(path);
      }

      // clean up the relative directory references
      // TODO: This is a somewhat slow process because the string tokenizer
      //       isn't setup to be run in reverse, which is the most efficient
      //       way to build a directory path. This could become an issue if
      //       the application is doing a ton of path normalizations. -- manu
      StringTokenizer st(tempPath.c_str(), '/');
      int nTokens = st.getTokenCount();
      int skipNum = 0;
      tempPath.erase();
      for(int i = nTokens - 1; i > 0; i--)
      {
         const char* token = st.getToken(i);
         if(strcmp(token, "..") == 0)
         {
            skipNum++;
         }
         else if(strcmp(token, ".") == 0)
         {

         }
         else
         {
            if(skipNum == 0)
            {
               tempPath.insert(0, token);
               tempPath.insert(0, 1, '/');
            }
            else
            {
               skipNum--;
            }
         }
      }
   }

   normalizedPath.assign(tempPath);

   return rval;
}

bool File::normalizePath(File& path, string& normalizedPath)
{
   return normalizePath(path->getName(), normalizedPath);
}

bool File::expandUser(const char* path, string& expandedPath)
{
   bool rval = true;
   size_t pathlen = 0;

   if(path != NULL)
   {
      pathlen = strlen(path);
   }

   if(pathlen > 0 && path[0] == '~')
   {
      // FIXME add getpwnam support
      // only handle current user right now
      if(pathlen > 1 && path[1] != '/')
      {
         ExceptionRef e = new Exception(
            "db::io::File::expandUser only supports current "
            "user (ie, \"~/...\").");
         Exception::setLast(e, false);
         rval = false;
      }
      else
      {
         const char* home = getenv("HOME");
         if(home != NULL)
         {
            // add HOME
            expandedPath.assign(home);
            // add rest of path
            expandedPath.append(path+1);
         }
         else
         {
            // no HOME set
            ExceptionRef e = new Exception(
               "db::io::File::expandUser called without HOME set.");
            Exception::setLast(e, false);
            rval = false;
         }
      }
   }
   else
   {
      expandedPath.assign(path);
   }

   return rval;
}

bool File::getCurrentWorkingDirectory(string& cwd)
{
   bool rval = true;

   char* b = (char*)malloc(PATH_MAX);
   if(getcwd(b, PATH_MAX) != NULL)
   {
      cwd.assign(b);
   }
   else
   {
      // path was too large for getcwd
      ExceptionRef e = new Exception(
         "Could not get current working directory, path too long!");
      Exception::setLast(e, false);
      rval = false;
   }
   free(b);

   return rval;
}

bool File::isPathReadable(const char* path)
{
   return (access(path, R_OK) == 0);
}

bool File::isPathWritable(const char* path)
{
   return (access(path, W_OK) == 0);
}

void File::split(const char* path, string& dirname, string& basename)
{
   // FIXME: support non-posix paths
   string sPath = path;
   string::size_type pos = sPath.rfind('/') + 1;
   dirname.assign(sPath.substr(0, pos));
   basename.assign(sPath.substr(pos));
   if(dirname.length() > 0 && dirname != "/")
   {
      dirname.erase(dirname.find_last_not_of("/") + 1);
   }
}

void File::splitext(
   const char* path, string& root, string& ext, const char* sep)
{
   string sPath = path;
   string::size_type pos = sPath.rfind(sep);
   if(pos != string::npos)
   {
      root.assign(sPath.substr(0, pos));
      ext.assign(sPath.substr(pos));
   }
   else
   {
      root.assign(path);
      ext.clear();
   }
}

string File::parentname(const char* path)
{
   string dirname = File::dirname(path);
   if(strcmp(dirname.c_str(), path) == 0)
   {
      // drop last slash if dirname != "/"
      if(dirname.length() > 1)
      {
         dirname.erase(dirname.end());
         dirname = File::dirname(dirname.c_str());
      }
   }

   return dirname;
}

string File::dirname(const char* path)
{
   string dirname;
   string basename;

   File::split(path, dirname, basename);

   return dirname;
}

string File::basename(const char* path)
{
   string dirname;
   string basename;

   File::split(path, dirname, basename);

   return basename;
}

bool File::isPathAbsolute(const char* path)
{
   // FIXME: support non-posix paths.
   return path != NULL && strlen(path) > 0 && path[0] == '/';
}

string File::join(const char* component, ...)
{
   string path;
   const char* comp = component;
   va_list varargs;

   va_start(varargs, component);
   while(comp != NULL)
   {
      // FIXME: support non-posix paths.
      if(strlen(comp) > 0)
      {
         string::size_type plen = path.length();
         if(plen == 0)
         {
            // empty path, just assign comp
            path.assign(comp);
         }
         else
         {
            bool pslash = (path[plen - 1] == '/');
            bool cslash = (comp[0] == '/');
            if(!pslash && !cslash)
            {
               // no trailing path slash or leading comp slash
               path.push_back('/');
               path.append(comp);
            }
            else if(pslash && cslash)
            {
               // trailing and leading slash, skip one
               path.append(comp + 1);
            }
            else
            {
               // only one of trailing or leading, just append
               path.append(comp);
            }
         }
      }
      comp = va_arg(varargs, const char*);
   }
   va_end(varargs);

   return path;
}
<commit_msg>Fix string reassignment issue in expandUser.<commit_after>/*
 * Copyright (c) 2007-2008 Digital Bazaar, Inc.  All rights reserved.
 */
#include "db/io/File.h"

#include "db/io/FileFunctions.h"
#include "db/io/FileList.h"
#include "db/io/IOException.h"
#include "db/rt/DynamicObject.h"
#include "db/util/StringTokenizer.h"

#include <cstdlib>
#include <cstring>
#include <cstdarg>
#include <sys/stat.h>
#include <dirent.h>
#include <errno.h>
#include <vector>

using namespace std;
using namespace db::io;
using namespace db::rt;
using namespace db::util;

FileImpl::FileImpl()
{
   mName = strdup("");
}

FileImpl::FileImpl(const char* name)
{
   mName = strdup(name);
}

FileImpl::~FileImpl()
{
   free(mName);
}

bool FileImpl::create()
{
   bool rval = false;

   FILE* fp = fopen(mName, "w");
   if(fp != NULL)
   {
      rval = true;
      fclose(fp);
   }
   else
   {
      string msg = "Could not create file! ";
      msg.append(strerror(errno));
      ExceptionRef e = new IOException(msg.c_str());
      Exception::setLast(e, false);
   }

   return rval;
}

bool FileImpl::mkdirs()
{
   bool rval = true;

   // get path
   string path = (isDirectory() ? getName() : File::parentname(getName()));

   // create stack of directories
   vector<string> dirStack;
   dirStack.push_back(path);
   while(strcmp(path.c_str(), "/") != 0)
   {
      path = File::parentname(path.c_str());
      dirStack.push_back(path);
   }

   // iteratively create directories
   struct stat s;
   int rc;
   while(rval && !dirStack.empty())
   {
      path = dirStack.back();
      dirStack.pop_back();

      // try to stat directory
      rc = stat(path.c_str(), &s);
      if(rc != 0)
      {
         // Note: windows does not allow permissions in mkdir()
         // directory doesn't exist, so try to create it
         if(mkdir(path.c_str(), 0777) < 0)
         {
            string msg = "Could not make directory! ";
            msg.append(strerror(errno));
            ExceptionRef e = new IOException(msg.c_str());
            e->getDetails()["path"] = path.c_str();
            Exception::setLast(e, false);
            rval = false;
         }
      }
   }

   return rval;
}

bool FileImpl::exists()
{
   bool rval = false;

   struct stat s;
   int rc = stat(mName, &s);
   if(rc == 0)
   {
      rval = true;
   }
   else
   {
      // does not set an exception intentionally
   }

   return rval;
}

bool FileImpl::remove()
{
   bool rval = false;

   int rc = ::remove(mName);
   if(rc == 0)
   {
      rval = true;
   }
   else
   {
      // FIXME: want to make sure no exception is
      // set when the file didn't exist prior to deletion
//      string msg = "Could not delete file! ";
//      msg.append(strerror(errno));
//      ExceptionRef e = new IOException(msg.c_str());
//      Exception::setLast(e, false);
   }

   return rval;
}

bool FileImpl::rename(File& file)
{
   bool rval = false;

   // delete old file
   file->remove();

   // rename file
   int rc = ::rename(mName, file->getName());
   if(rc == 0)
   {
      rval = true;
   }
   else
   {
      string msg = "Could not rename file! ";
      msg.append(strerror(errno));
      ExceptionRef e = new IOException(msg.c_str());
      Exception::setLast(e, false);
   }

   return rval;
}

const char* FileImpl::getName() const
{
   return mName;
}

off_t FileImpl::getLength()
{
   struct stat s;
   int rc = stat(mName, &s);
   if(rc != 0)
   {
      string msg = "Could not stat file! ";
      msg.append(strerror(errno));
      ExceptionRef e = new IOException(msg.c_str());
      Exception::setLast(e, false);
   }

   return s.st_size;
}

FileImpl::Type FileImpl::getType()
{
   Type rval = Unknown;

   // use lstat so symbolic links aren't followed
   struct stat s;
   int rc = stat(mName, &s);
   if(rc != 0)
   {
   }
   else
   {
      switch(s.st_mode & S_IFMT)
      {
         case S_IFREG:
            rval = RegularFile;
            break;
         case S_IFDIR:
            rval = Directory;
            break;
         case S_IFLNK:
            rval = SymbolicLink;
            break;
         default:
            break;
      }
   }

   return rval;
}

bool FileImpl::isFile()
{
   return getType() == RegularFile;
}

bool FileImpl::contains(const char* path)
{
   bool rval = false;
   string normalizedContainer;
   string normalizedFileImpl;

   if(File::normalizePath(getName(), normalizedContainer) &&
      File::normalizePath(path, normalizedFileImpl))
   {
      rval = (normalizedFileImpl.find(normalizedContainer, 0) == 0);
   }

   return rval;
}

bool FileImpl::contains(File& path)
{
   return contains(path->getName());
}

bool FileImpl::isDirectory()
{
   return getType() == Directory;
}

bool FileImpl::isReadable()
{
   bool rval = false;
   string npath;

   if(File::normalizePath(getName(), npath))
   {
      rval = File::isPathReadable(npath.c_str());
   }

   return rval;
}

bool FileImpl::isSymbolicLink()
{
   return getType() == SymbolicLink;
}

bool FileImpl::isWritable()
{
   bool rval = false;
   string npath;

   if(File::normalizePath(getName(), npath))
   {
      rval = File::isPathWritable(npath.c_str());
   }

   return rval;
}

void FileImpl::listFiles(FileList& files)
{
   if(isDirectory())
   {
      // open directory
      DIR* dir = opendir(mName);
      if(dir == NULL)
      {
         // FIXME: add error handling
      }
      else
      {
         // read each directory entry
         struct dirent* entry;
         unsigned int len1 = strlen(mName);
         bool separator = mName[len1 - 1] != '/';
         while((entry = readdir(dir)) != NULL)
         {
            // d_name is null-terminated name for FileImpl, without path name
            // so copy FileImpl name before d_name to get full path
            unsigned int len2 = strlen(entry->d_name);
            char path[len1 + len2 + 2];
            memcpy(path, mName, len1);
            if(separator)
            {
               // add path separator as appropriate
               path[len1] = '/';
               memcpy(path + len1 + 1, entry->d_name, len2 + 1);
            }
            else
            {
               memcpy(path + len1, entry->d_name, len2 + 1);
            }

            // add new FileImpl to list
            File file(path);
            files->add(file);
         }

         // close directory
         closedir(dir);
      }
   }
}

Date FileImpl::getModifiedDate()
{
   Date date(0);
   struct stat s;

   if(stat(mName, &s) == 0)
   {
      date.setSeconds(s.st_mtime);
   }

   return date;
}

bool File::operator==(const File& rhs) const
{
   bool rval = false;

   File& file = *((File*)&rhs);

   // compare names and types for equality
   if(strcmp((*this)->getName(), file->getName()) == 0)
   {
      rval = ((*this)->getType() == file->getType());
   }

   return rval;
}

bool File::normalizePath(const char* path, string& normalizedPath)
{
   bool rval = true;
   string tempPath;

   if(strlen(path) > 0)
   {
      // if the path isn't absolute, pre-pend the current working directory
      // to the path.
      if(path[0] != '/')
      {
         rval = getCurrentWorkingDirectory(tempPath);

         tempPath.push_back('/');
         tempPath.append(path);
      }
      else
      {
         tempPath.append(path);
      }

      // clean up the relative directory references
      // TODO: This is a somewhat slow process because the string tokenizer
      //       isn't setup to be run in reverse, which is the most efficient
      //       way to build a directory path. This could become an issue if
      //       the application is doing a ton of path normalizations. -- manu
      StringTokenizer st(tempPath.c_str(), '/');
      int nTokens = st.getTokenCount();
      int skipNum = 0;
      tempPath.erase();
      for(int i = nTokens - 1; i > 0; i--)
      {
         const char* token = st.getToken(i);
         if(strcmp(token, "..") == 0)
         {
            skipNum++;
         }
         else if(strcmp(token, ".") == 0)
         {

         }
         else
         {
            if(skipNum == 0)
            {
               tempPath.insert(0, token);
               tempPath.insert(0, 1, '/');
            }
            else
            {
               skipNum--;
            }
         }
      }
   }

   normalizedPath.assign(tempPath);

   return rval;
}

bool File::normalizePath(File& path, string& normalizedPath)
{
   return normalizePath(path->getName(), normalizedPath);
}

bool File::expandUser(const char* path, string& expandedPath)
{
   bool rval = true;
   size_t pathlen = 0;

   if(path != NULL)
   {
      pathlen = strlen(path);
   }

   if(pathlen > 0 && path[0] == '~')
   {
      // FIXME add getpwnam support
      // only handle current user right now
      if(pathlen > 1 && path[1] != '/')
      {
         ExceptionRef e = new Exception(
            "db::io::File::expandUser only supports current "
            "user (ie, \"~/...\").");
         Exception::setLast(e, false);
         rval = false;
      }
      else
      {
         const char* home = getenv("HOME");
         if(home != NULL)
         {
            // use temp string to avoid problems if path is same expandedPath
            // common for code like expandUser(path.c_str(), path)
            // add HOME
            string newPath(home);
            // add rest of path
            newPath.append(path+1);
            // copy to output
            expandedPath.assign(newPath);
         }
         else
         {
            // no HOME set
            ExceptionRef e = new Exception(
               "db::io::File::expandUser called without HOME set.");
            Exception::setLast(e, false);
            rval = false;
         }
      }
   }
   else
   {
      expandedPath.assign(path);
   }

   return rval;
}

bool File::getCurrentWorkingDirectory(string& cwd)
{
   bool rval = true;

   char* b = (char*)malloc(PATH_MAX);
   if(getcwd(b, PATH_MAX) != NULL)
   {
      cwd.assign(b);
   }
   else
   {
      // path was too large for getcwd
      ExceptionRef e = new Exception(
         "Could not get current working directory, path too long!");
      Exception::setLast(e, false);
      rval = false;
   }
   free(b);

   return rval;
}

bool File::isPathReadable(const char* path)
{
   return (access(path, R_OK) == 0);
}

bool File::isPathWritable(const char* path)
{
   return (access(path, W_OK) == 0);
}

void File::split(const char* path, string& dirname, string& basename)
{
   // FIXME: support non-posix paths
   string sPath = path;
   string::size_type pos = sPath.rfind('/') + 1;
   dirname.assign(sPath.substr(0, pos));
   basename.assign(sPath.substr(pos));
   if(dirname.length() > 0 && dirname != "/")
   {
      dirname.erase(dirname.find_last_not_of("/") + 1);
   }
}

void File::splitext(
   const char* path, string& root, string& ext, const char* sep)
{
   string sPath = path;
   string::size_type pos = sPath.rfind(sep);
   if(pos != string::npos)
   {
      root.assign(sPath.substr(0, pos));
      ext.assign(sPath.substr(pos));
   }
   else
   {
      root.assign(path);
      ext.clear();
   }
}

string File::parentname(const char* path)
{
   string dirname = File::dirname(path);
   if(strcmp(dirname.c_str(), path) == 0)
   {
      // drop last slash if dirname != "/"
      if(dirname.length() > 1)
      {
         dirname.erase(dirname.end());
         dirname = File::dirname(dirname.c_str());
      }
   }

   return dirname;
}

string File::dirname(const char* path)
{
   string dirname;
   string basename;

   File::split(path, dirname, basename);

   return dirname;
}

string File::basename(const char* path)
{
   string dirname;
   string basename;

   File::split(path, dirname, basename);

   return basename;
}

bool File::isPathAbsolute(const char* path)
{
   // FIXME: support non-posix paths.
   return path != NULL && strlen(path) > 0 && path[0] == '/';
}

string File::join(const char* component, ...)
{
   string path;
   const char* comp = component;
   va_list varargs;

   va_start(varargs, component);
   while(comp != NULL)
   {
      // FIXME: support non-posix paths.
      if(strlen(comp) > 0)
      {
         string::size_type plen = path.length();
         if(plen == 0)
         {
            // empty path, just assign comp
            path.assign(comp);
         }
         else
         {
            bool pslash = (path[plen - 1] == '/');
            bool cslash = (comp[0] == '/');
            if(!pslash && !cslash)
            {
               // no trailing path slash or leading comp slash
               path.push_back('/');
               path.append(comp);
            }
            else if(pslash && cslash)
            {
               // trailing and leading slash, skip one
               path.append(comp + 1);
            }
            else
            {
               // only one of trailing or leading, just append
               path.append(comp);
            }
         }
      }
      comp = va_arg(varargs, const char*);
   }
   va_end(varargs);

   return path;
}
<|endoftext|>


<commit_before>#include "typedbytes.h"
#include "stdio.h"

#include <string>
#include <vector>

#define IS_TYPEDBYTES_BYTE_SEQUENCE(type) ((type) >= 50 && (type) <= 200)

static inline void push_opaque_typecode(typedbytes_opaque& buffer,
                                        TypedBytesType code) {
  buffer.push_back((unsigned char) code);
}

static inline void push_opaque_bytes(typedbytes_opaque& buffer,
                                     unsigned char* bytes, size_t size) {
  while (size > 0) {
    buffer.push_back(*bytes);
    ++bytes;
    --size;
  }
}

static inline void push_opaque_length(typedbytes_opaque& buffer,
                                      typedbytes_length len) {
  len = bswap32(len);
  push_opaque_bytes(buffer, (unsigned char*)&len, sizeof(typedbytes_length));
}

bool TypedBytesInFile::_read_opaque_primitive(typedbytes_opaque& buffer,
                                              TypedBytesType t) {
  // TODO check the fread commands in this function
  unsigned char bytebuf = 0;
  int32_t intbuf = 0;
  int64_t longbuf = 0;
  typedbytes_length len = 0;

  // NOTE the typecode has already been pushed

  // translate this type to avoid nastiness in the switch.
  if (IS_TYPEDBYTES_BYTE_SEQUENCE(t)) {
    t = TypedBytesByteSequence;
  }
  switch (t) {
  case TypedBytesByte:
  case TypedBytesBoolean:
    fread(&bytebuf, sizeof(unsigned char), 1, stream_);
    push_opaque_bytes(buffer, &bytebuf, sizeof(unsigned char));
    break;

  case TypedBytesInteger:
  case TypedBytesFloat:
    fread(&intbuf, sizeof(int32_t), 1, stream_);
    push_opaque_bytes(buffer, (unsigned char*) &intbuf, sizeof(int32_t));
    break;

  case TypedBytesLong:
  case TypedBytesDouble:
    fread(&longbuf, sizeof(int64_t), 1, stream_);
    push_opaque_bytes(buffer, (unsigned char*) &longbuf, sizeof(int64_t));
    break;

  case TypedBytesString:
  case TypedBytesByteSequence:
    len = _read_length();
    while (len > 0) {
      // stream_ to buffer in longbuf bytes at a time.
      if (len >= 8) {
        fread(&longbuf, sizeof(int64_t), 1, stream_);
        push_opaque_bytes(buffer, (unsigned char*) &longbuf, sizeof(int64_t));
        len -= sizeof(int64_t);
      } else {
        fread(&longbuf, len, 1, stream_);
        push_opaque_bytes(buffer, (unsigned char*) &longbuf, len);
        break;
      }
    }
    break;

  default:
    return false;
  }
  return true;
}

bool TypedBytesInFile::_read_opaque(typedbytes_opaque& buffer, bool list) {
  TypedBytesType t = next_type();
  push_opaque_typecode(buffer, t);
  if (t == TypedBytesByteSequence || t == TypedBytesByte ||
      t == TypedBytesBoolean || t == TypedBytesInteger || t==TypedBytesLong ||
      t == TypedBytesFloat || t == TypedBytesDouble ||
      t == TypedBytesString || IS_TYPEDBYTES_BYTE_SEQUENCE(t)) {
    _read_opaque_primitive(buffer, t);
  } else if (t == TypedBytesVector) {
    typedbytes_length len = read_typedbytes_sequence_length();
    push_opaque_length(buffer, len);
    for (int i = 0; i < len; ++i) {
      _read_opaque(buffer, false);
    }
  } else if(t == TypedBytesMap) {
    typedbytes_length len = read_typedbytes_sequence_length();
    push_opaque_length(buffer, len);
    for (int i = 0; i < len; ++i) {
      _read_opaque(buffer, false);
      _read_opaque(buffer, false);
    }
  } else if (t == TypedBytesList) {
    while (last_code_ != TypedBytesListEnd) {
      _read_opaque(buffer, true);
    }
  } else if (list && t == TypedBytesListEnd) {
    return true;
  } else {
    return false;
  }
  return true;
}

bool TypedBytesInFile::read_opaque(typedbytes_opaque& buffer) {
  return _read_opaque(buffer, false);
}

bool TypedBytesInFile::skip_next() {
  // TODO, rewrite these functions to avoid loading into memory
  typedbytes_opaque value;
  return read_opaque(value);
}

TypedBytesType TypedBytesInFile::next_type() {
  unsigned char code = next_type_code();
  if (code <= 10 || code == 255) {
    return (TypedBytesType)code;
  } else if (IS_TYPEDBYTES_BYTE_SEQUENCE(code)) {
    return TypedBytesByteSequence;
  } else if (code == TypedBytesTypeError) {
    // error flag already set in this case.
    return TypedBytesTypeError;
  } else {
    // TODO set error flag
    return TypedBytesTypeError;
  }
}

unsigned char TypedBytesInFile::next_type_code() {
  int c = fgetc(stream_);
  // reset last_length_
  last_length_ = -1;
  if (c == EOF) {
    // TODO set error flag
    last_code_ = TypedBytesTypeError;
    return (unsigned char) TypedBytesTypeError;
  } else {
    last_code_ = (TypedBytesType) c;
    return (unsigned char) c;
  }
}

size_t TypedBytesInFile::_read_bytes(void *ptr, size_t nbytes, size_t nelem) {
  size_t nread = fread(ptr, nbytes, nelem, stream_);
  if (nread != nelem) {
    // TODO set error flag and determine more intelligent action.
    assert(0);
  }
  // reset last_length_
  last_length_ = -1;
  return nread;
}

int32_t TypedBytesInFile::_read_length() {
  int32_t len = 0;
  _read_bytes(&len, sizeof(int32_t), 1);
  len = bswap32(len);
  return len;
}

bool TypedBytesInFile::_read_data_block(unsigned char* data, size_t size) {
  assert(last_length_ >= 0);
  typedbytes_length curlen = last_length_;
  if (size > (size_t) curlen) {
    return false;
  }
  size_t nread = _read_bytes(data, sizeof(unsigned char), (size_t) size);
  // NOTE _read_bytes resets last_length_, so we have to reset it back
  if (nread != size) {
    // TODO update error
    return false;
  }
  last_length_ = curlen - size;
  assert(last_length_ >= 0);
  return true;
}

#ifdef TYPEDBYTES_STRICT_TYPE
# define typedbytes_check_type_code(x) (assert((x) == last_code_))
#else
# define typedbytes_check_type_code(x)
#endif

signed char TypedBytesInFile::read_byte() {
  typedbytes_check_type_code(TypedBytesByte);
  signed char rval = 0;
  _read_bytes(&rval, sizeof(signed char), 1);
  return (rval);
}

bool TypedBytesInFile::read_bool() {
  typedbytes_check_type_code(TypedBytesBoolean);
  signed char rval = 0;
  _read_bytes(&rval, sizeof(signed char), 1);
  return (bool)rval;
}

float TypedBytesInFile::read_float() {
  typedbytes_check_type_code(TypedBytesFloat);
  int32_t val = 0;
  _read_bytes(&val, sizeof(int32_t), 1);
  val = bswap32(val);
  float rval;
  memcpy(&rval, &val, sizeof(int32_t));
  return rval;
}

double TypedBytesInFile::read_double() {
  typedbytes_check_type_code(TypedBytesDouble);
  int64_t val = 0;
  _read_bytes(&val, sizeof(int64_t), 1);
  val = bswap64(val);
  double rval;
  memcpy(&rval, &val, sizeof(int64_t));
  return rval;
}

double TypedBytesInFile::convert_double() {
  if (last_code_ == TypedBytesFloat) {
    return (double) read_float();
  } else if (last_code_ == TypedBytesDouble) {
    return (double) read_double();
  } else {
    return (double) convert_long();
  }
}

typedbytes_long TypedBytesInFile::convert_long() {
  if (last_code_ == TypedBytesLong) {
    return (long) read_long();
  } else {
    return (long) convert_int();
  }
}

int TypedBytesInFile::convert_int() {
  if (last_code_ == TypedBytesByte) {
    return (int) read_byte();
  } else if (last_code_ == TypedBytesBoolean) {
    return (int) read_bool();
  } else if (last_code_ == TypedBytesInteger) {
    return (int) read_int();
  } else {
    assert(last_code_ == TypedBytesTypeError);
    return 0;
  }
}

int TypedBytesInFile::read_int() {
  typedbytes_check_type_code(TypedBytesInteger);
  int32_t rval = 0;
  _read_bytes(&rval, sizeof(int32_t), 1);
  rval = bswap32(rval);
  return (int) rval;
}

typedbytes_long TypedBytesInFile::read_long() {
  typedbytes_check_type_code(TypedBytesLong);
  int64_t rval = 0;
  _read_bytes(&rval, sizeof(int64_t), 1);
  rval = bswap64(rval);
  return (typedbytes_long) rval;
}

typedbytes_length TypedBytesInFile::read_string_length() {
  typedbytes_check_type_code(TypedBytesString);
  typedbytes_length len = _read_length();
  last_length_ = len;
  return len;
}

bool TypedBytesInFile::read_string_data(unsigned char* data, size_t size) {
  typedbytes_check_type_code(TypedBytesString);
  return _read_data_block(data, size);
}

bool TypedBytesInFile::read_string(std::string& str) {
  typedbytes_check_type_code(TypedBytesString);
  typedbytes_length len = _read_length();
  str.resize(len);
  assert(len >= 0);
  // TODO check for error
  _read_bytes(&str[0], sizeof(unsigned char), (size_t) len);
  return true;
}

typedbytes_length TypedBytesInFile::read_byte_sequence_length() {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ == TypedBytesByteSequence ||
      IS_TYPEDBYTES_BYTE_SEQUENCE(last_code_)) {
    // do nothing here
  } else {
    typedbytes_check_type_code(TypedBytesTypeError);
  }
#endif
  typedbytes_length len = _read_length();
  last_length_ = len;
  return len;
}

bool TypedBytesInFile::read_byte_sequence(unsigned char* data, size_t size) {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ == TypedBytesByteSequence ||
      IS_TYPEDBYTES_BYTE_SEQUENCE(last_code_)) {
    // do nothing here
  } else {
    typedbytes_check_type_code(TypedBytesTypeError);
  }
#endif
  return _read_data_block(data, size);
}

typedbytes_length TypedBytesInFile::read_typedbytes_sequence_length() {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ == TypedBytesVector || last_code_ == TypedBytesMap) {
    // do nothing here
  } else {
    typedbytes_check_type_code(TypedBytesTypeError);
  }
#endif
  return _read_length();
}

bool TypedBytesOutFile::_write_length(typedbytes_length len) {
  len = bswap32(len);
  return fwrite(&len, sizeof(typedbytes_length), 1, stream_) == 1;
}

bool TypedBytesOutFile::_write_code(TypedBytesType t) {
  unsigned char code = (unsigned char) t;
  return _write_bytes(&code, 1, 1);
}

bool TypedBytesOutFile::write_bool(bool val) {
  signed char sval = 0;
  if (val) {
    sval = 1;
  }
  return _write_code(TypedBytesBoolean) && _write_bytes(&sval, 1, 1);
}

bool TypedBytesOutFile::write_int(int val) {
  int32_t sval = bswap32(val);
  return _write_code(TypedBytesInteger) &&
    _write_bytes(&sval, sizeof(int32_t), 1);
}

bool TypedBytesOutFile::write_long(typedbytes_long val) {
  val = bswap64(val);
  return _write_code(TypedBytesLong) &&
    _write_bytes(&val, sizeof(typedbytes_long), 1);
}

bool TypedBytesOutFile::write_float(float val) {
  int32_t sval = 0;
  memcpy(&sval, &val, sizeof(int32_t));
  sval = bswap32(sval);
  return _write_code(TypedBytesFloat) && _write_bytes(&sval, sizeof(int32_t), 1);
}

bool TypedBytesOutFile::write_double(double val) {
  int64_t sval = 0;
  memcpy(&sval, &val, sizeof(int64_t));
  sval = bswap64(sval);
  return _write_code(TypedBytesDouble) &&
    _write_bytes(&sval, sizeof(int64_t), 1);
}
<commit_msg>cleanup<commit_after>#include "typedbytes.h"
#include "stdio.h"

#include <string>
#include <vector>

#define IS_TYPEDBYTES_BYTE_SEQUENCE(type) ((type) >= 50 && (type) <= 200)

static inline void push_opaque_typecode(typedbytes_opaque& buffer,
                                        TypedBytesType code) {
  buffer.push_back((unsigned char) code);
}

static inline void push_opaque_bytes(typedbytes_opaque& buffer,
                                     unsigned char* bytes, size_t size) {
  while (size > 0) {
    buffer.push_back(*bytes);
    ++bytes;
    --size;
  }
}

static inline void push_opaque_length(typedbytes_opaque& buffer,
                                      typedbytes_length len) {
  len = bswap32(len);
  push_opaque_bytes(buffer, (unsigned char*)&len, sizeof(typedbytes_length));
}

bool TypedBytesInFile::_read_opaque_primitive(typedbytes_opaque& buffer,
                                              TypedBytesType t) {
  // TODO check the fread commands in this function
  unsigned char bytebuf = 0;
  int32_t intbuf = 0;
  int64_t longbuf = 0;
  typedbytes_length len = 0;

  // NOTE the typecode has already been pushed

  // translate this type to avoid nastiness in the switch.
  if (IS_TYPEDBYTES_BYTE_SEQUENCE(t)) {
    t = TypedBytesByteSequence;
  }
  switch (t) {
  case TypedBytesByte:
  case TypedBytesBoolean:
    fread(&bytebuf, sizeof(unsigned char), 1, stream_);
    push_opaque_bytes(buffer, &bytebuf, sizeof(unsigned char));
    break;

  case TypedBytesInteger:
  case TypedBytesFloat:
    fread(&intbuf, sizeof(int32_t), 1, stream_);
    push_opaque_bytes(buffer, (unsigned char*) &intbuf, sizeof(int32_t));
    break;

  case TypedBytesLong:
  case TypedBytesDouble:
    fread(&longbuf, sizeof(int64_t), 1, stream_);
    push_opaque_bytes(buffer, (unsigned char*) &longbuf, sizeof(int64_t));
    break;

  case TypedBytesString:
  case TypedBytesByteSequence:
    len = _read_length();
    while (len > 0) {
      // stream_ to buffer in longbuf bytes at a time.
      if (len >= 8) {
        fread(&longbuf, sizeof(int64_t), 1, stream_);
        push_opaque_bytes(buffer, (unsigned char*) &longbuf, sizeof(int64_t));
        len -= sizeof(int64_t);
      } else {
        fread(&longbuf, len, 1, stream_);
        push_opaque_bytes(buffer, (unsigned char*) &longbuf, len);
        break;
      }
    }
    break;

  default:
    return false;
  }
  return true;
}

bool TypedBytesInFile::_read_opaque(typedbytes_opaque& buffer, bool list) {
  TypedBytesType t = next_type();
  push_opaque_typecode(buffer, t);
  if (t == TypedBytesByteSequence || t == TypedBytesByte ||
      t == TypedBytesBoolean || t == TypedBytesInteger || t==TypedBytesLong ||
      t == TypedBytesFloat || t == TypedBytesDouble ||
      t == TypedBytesString || IS_TYPEDBYTES_BYTE_SEQUENCE(t)) {
    _read_opaque_primitive(buffer, t);
  } else if (t == TypedBytesVector) {
    typedbytes_length len = read_typedbytes_sequence_length();
    push_opaque_length(buffer, len);
    for (int i = 0; i < len; ++i) {
      _read_opaque(buffer, false);
    }
  } else if(t == TypedBytesMap) {
    typedbytes_length len = read_typedbytes_sequence_length();
    push_opaque_length(buffer, len);
    for (int i = 0; i < len; ++i) {
      _read_opaque(buffer, false);
      _read_opaque(buffer, false);
    }
  } else if (t == TypedBytesList) {
    while (last_code_ != TypedBytesListEnd) {
      _read_opaque(buffer, true);
    }
  } else if (list && t == TypedBytesListEnd) {
    return true;
  } else {
    return false;
  }
  return true;
}

bool TypedBytesInFile::read_opaque(typedbytes_opaque& buffer) {
  return _read_opaque(buffer, false);
}

bool TypedBytesInFile::skip_next() {
  // TODO, rewrite these functions to avoid loading into memory
  typedbytes_opaque value;
  return read_opaque(value);
}

TypedBytesType TypedBytesInFile::next_type() {
  unsigned char code = next_type_code();
  if (code <= 10 || code == 255) {
    return (TypedBytesType) code;
  } else if (IS_TYPEDBYTES_BYTE_SEQUENCE(code)) {
    return TypedBytesByteSequence;
  } else if (code == TypedBytesTypeError) {
    // error flag already set in this case.
    return TypedBytesTypeError;
  } else {
    // TODO set error flag
    return TypedBytesTypeError;
  }
}

unsigned char TypedBytesInFile::next_type_code() {
  int c = fgetc(stream_);
  // reset last_length_
  last_length_ = -1;
  if (c == EOF) {
    // TODO set error flag
    last_code_ = TypedBytesTypeError;
    return (unsigned char) TypedBytesTypeError;
  } else {
    last_code_ = (TypedBytesType) c;
    return (unsigned char) c;
  }
}

size_t TypedBytesInFile::_read_bytes(void *ptr, size_t nbytes, size_t nelem) {
  size_t nread = fread(ptr, nbytes, nelem, stream_);
  // TODO set error flag and determine more intelligent action.
  assert(nread == nelem);
  // reset last_length_
  last_length_ = -1;
  return nread;
}

int32_t TypedBytesInFile::_read_length() {
  int32_t len = 0;
  _read_bytes(&len, sizeof(int32_t), 1);
  len = bswap32(len);
  return len;
}

bool TypedBytesInFile::_read_data_block(unsigned char* data, size_t size) {
  assert(last_length_ >= 0);
  typedbytes_length curlen = last_length_;
  if (size > (size_t) curlen) {
    return false;
  }
  size_t nread = _read_bytes(data, sizeof(unsigned char), (size_t) size);
  // NOTE _read_bytes resets last_length_, so we have to reset it back
  if (nread != size) {
    // TODO update error
    return false;
  }
  last_length_ = curlen - size;
  assert(last_length_ >= 0);
  return true;
}

#ifdef TYPEDBYTES_STRICT_TYPE
# define typedbytes_check_type_code(x) (assert((x) == last_code_))
#else
# define typedbytes_check_type_code(x)
#endif

signed char TypedBytesInFile::read_byte() {
  typedbytes_check_type_code(TypedBytesByte);
  signed char rval = 0;
  _read_bytes(&rval, sizeof(signed char), 1);
  return (rval);
}

bool TypedBytesInFile::read_bool() {
  typedbytes_check_type_code(TypedBytesBoolean);
  signed char rval = 0;
  _read_bytes(&rval, sizeof(signed char), 1);
  return (bool) rval;
}

float TypedBytesInFile::read_float() {
  typedbytes_check_type_code(TypedBytesFloat);
  int32_t val = 0;
  _read_bytes(&val, sizeof(int32_t), 1);
  val = bswap32(val);
  float rval;
  memcpy(&rval, &val, sizeof(int32_t));
  return rval;
}

double TypedBytesInFile::read_double() {
  typedbytes_check_type_code(TypedBytesDouble);
  int64_t val = 0;
  _read_bytes(&val, sizeof(int64_t), 1);
  val = bswap64(val);
  double rval;
  memcpy(&rval, &val, sizeof(int64_t));
  return rval;
}

double TypedBytesInFile::convert_double() {
  switch (last_code_) {
  case TypedBytesFloat:
    return (double) read_float();
  case TypedBytesDouble:
    return read_double();
  default:
    return (double) convert_long();
  }
}

typedbytes_long TypedBytesInFile::convert_long() {
  if (last_code_ == TypedBytesLong)
    return read_long();
  return (long) convert_int();
}

int TypedBytesInFile::convert_int() {
  switch (last_code_) {
  case TypedBytesByte:
    return (int) read_byte();
  case TypedBytesBoolean:
    return (int) read_bool();
  case TypedBytesInteger:
    return read_int();
  default:
    assert(last_code_ == TypedBytesTypeError);
    return 0;
  }
}

int TypedBytesInFile::read_int() {
  typedbytes_check_type_code(TypedBytesInteger);
  int32_t rval = 0;
  _read_bytes(&rval, sizeof(int32_t), 1);
  rval = bswap32(rval);
  return (int) rval;
}

typedbytes_long TypedBytesInFile::read_long() {
  typedbytes_check_type_code(TypedBytesLong);
  int64_t rval = 0;
  _read_bytes(&rval, sizeof(int64_t), 1);
  rval = bswap64(rval);
  return (typedbytes_long) rval;
}

typedbytes_length TypedBytesInFile::read_string_length() {
  typedbytes_check_type_code(TypedBytesString);
  typedbytes_length len = _read_length();
  last_length_ = len;
  return len;
}

bool TypedBytesInFile::read_string_data(unsigned char* data, size_t size) {
  typedbytes_check_type_code(TypedBytesString);
  return _read_data_block(data, size);
}

bool TypedBytesInFile::read_string(std::string& str) {
  typedbytes_check_type_code(TypedBytesString);
  typedbytes_length len = _read_length();
  str.resize(len);
  assert(len >= 0);
  // TODO check for error
  _read_bytes(&str[0], sizeof(unsigned char), (size_t) len);
  return true;
}

typedbytes_length TypedBytesInFile::read_byte_sequence_length() {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ == TypedBytesByteSequence ||
      IS_TYPEDBYTES_BYTE_SEQUENCE(last_code_)) {
    // do nothing here
  } else {
    typedbytes_check_type_code(TypedBytesTypeError);
  }
#endif
  typedbytes_length len = _read_length();
  last_length_ = len;
  return len;
}

bool TypedBytesInFile::read_byte_sequence(unsigned char* data, size_t size) {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ == TypedBytesByteSequence ||
      IS_TYPEDBYTES_BYTE_SEQUENCE(last_code_)) {
    // do nothing here
  } else {
    typedbytes_check_type_code(TypedBytesTypeError);
  }
#endif
  return _read_data_block(data, size);
}

typedbytes_length TypedBytesInFile::read_typedbytes_sequence_length() {
#ifdef TYPEDBYTES_STRICT_TYPE
  if (last_code_ == TypedBytesVector || last_code_ == TypedBytesMap) {
    // do nothing here
  } else {
    typedbytes_check_type_code(TypedBytesTypeError);
  }
#endif
  return _read_length();
}

bool TypedBytesOutFile::_write_length(typedbytes_length len) {
  len = bswap32(len);
  return fwrite(&len, sizeof(typedbytes_length), 1, stream_) == 1;
}

bool TypedBytesOutFile::_write_code(TypedBytesType t) {
  unsigned char code = (unsigned char) t;
  return _write_bytes(&code, 1, 1);
}

bool TypedBytesOutFile::write_bool(bool val) {
  signed char sval = 0;
  if (val) {
    sval = 1;
  }
  return _write_code(TypedBytesBoolean) && _write_bytes(&sval, 1, 1);
}

bool TypedBytesOutFile::write_int(int val) {
  int32_t sval = bswap32(val);
  return _write_code(TypedBytesInteger) &&
    _write_bytes(&sval, sizeof(int32_t), 1);
}

bool TypedBytesOutFile::write_long(typedbytes_long val) {
  val = bswap64(val);
  return _write_code(TypedBytesLong) &&
    _write_bytes(&val, sizeof(typedbytes_long), 1);
}

bool TypedBytesOutFile::write_float(float val) {
  int32_t sval = 0;
  memcpy(&sval, &val, sizeof(int32_t));
  sval = bswap32(sval);
  return _write_code(TypedBytesFloat) && _write_bytes(&sval, sizeof(int32_t), 1);
}

bool TypedBytesOutFile::write_double(double val) {
  int64_t sval = 0;
  memcpy(&sval, &val, sizeof(int64_t));
  sval = bswap64(sval);
  return _write_code(TypedBytesDouble) &&
    _write_bytes(&sval, sizeof(int64_t), 1);
}
<|endoftext|>


<commit_before>#include <bench/tests/all_tests.hpp>
#include <bench/tests/dummy/cleanup_fail.hpp>
#include <bench/tests/dummy/setup_fail.hpp>
#include <bench/tests/dummy/test_fail.hpp>
#include <bench/tests/qdb/blob_add_tag.hpp>
#include <bench/tests/qdb/blob_get.hpp>
#include <bench/tests/qdb/blob_get_noalloc.hpp>
#include <bench/tests/qdb/blob_put.hpp>
#include <bench/tests/qdb/blob_remove.hpp>
#include <bench/tests/qdb/blob_update.hpp>
#include <bench/tests/qdb/deque_pop_back.hpp>
#include <bench/tests/qdb/deque_pop_front.hpp>
#include <bench/tests/qdb/deque_push_back.hpp>
#include <bench/tests/qdb/deque_push_front.hpp>
#include <bench/tests/qdb/hset_contains.hpp>
#include <bench/tests/qdb/hset_erase.hpp>
#include <bench/tests/qdb/hset_insert.hpp>
#include <bench/tests/qdb/int_add.hpp>
#include <bench/tests/qdb/int_get.hpp>
#include <bench/tests/qdb/int_put.hpp>
#include <bench/tests/qdb/int_remove.hpp>
#include <bench/tests/qdb/int_update.hpp>
#include <bench/tests/qdb/tag_add_blob.hpp>
#include <bench/tests/stdio/fread.hpp>
#include <bench/tests/stdio/fwrite.hpp>

bench::test_class_collection bench::tests::get_all_tests()
{
    // clang-format off
    return
    {
      // new dummy::setup_fail::test_class(),
      // new dummy::test_fail::test_class(),
      // new dummy::cleanup_fail::test_class(),
      new qdb::blob_add_tag::test_class(),
      new qdb::blob_get::test_class(),
      new qdb::blob_get_noalloc::test_class(),
      new qdb::blob_put::test_class(),
      new qdb::blob_remove::test_class(),
      new qdb::blob_update::test_class(),
      new qdb::deque_pop_back::test_class(),
      new qdb::deque_pop_front::test_class(),
      new qdb::deque_push_back::test_class(),
      new qdb::deque_push_front::test_class(),
      new qdb::hset_contains::test_class(),
      new qdb::hset_erase::test_class(),
      new qdb::hset_insert::test_class(),
      new qdb::int_add::test_class(),
      new qdb::int_get::test_class(),
      new qdb::int_put::test_class(),
      new qdb::int_remove::test_class(),
      new qdb::int_update::test_class(),
      new qdb::tag_add_blob::test_class(),
      new stdio::fread::test_class(),
      new stdio::fwrite::test_class(),
    };
}
<commit_msg>Disable test qdb_tag_and_blob because it's too long<commit_after>#include <bench/tests/all_tests.hpp>
#include <bench/tests/dummy/cleanup_fail.hpp>
#include <bench/tests/dummy/setup_fail.hpp>
#include <bench/tests/dummy/test_fail.hpp>
#include <bench/tests/qdb/blob_add_tag.hpp>
#include <bench/tests/qdb/blob_get.hpp>
#include <bench/tests/qdb/blob_get_noalloc.hpp>
#include <bench/tests/qdb/blob_put.hpp>
#include <bench/tests/qdb/blob_remove.hpp>
#include <bench/tests/qdb/blob_update.hpp>
#include <bench/tests/qdb/deque_pop_back.hpp>
#include <bench/tests/qdb/deque_pop_front.hpp>
#include <bench/tests/qdb/deque_push_back.hpp>
#include <bench/tests/qdb/deque_push_front.hpp>
#include <bench/tests/qdb/hset_contains.hpp>
#include <bench/tests/qdb/hset_erase.hpp>
#include <bench/tests/qdb/hset_insert.hpp>
#include <bench/tests/qdb/int_add.hpp>
#include <bench/tests/qdb/int_get.hpp>
#include <bench/tests/qdb/int_put.hpp>
#include <bench/tests/qdb/int_remove.hpp>
#include <bench/tests/qdb/int_update.hpp>
#include <bench/tests/qdb/tag_add_blob.hpp>
#include <bench/tests/stdio/fread.hpp>
#include <bench/tests/stdio/fwrite.hpp>

bench::test_class_collection bench::tests::get_all_tests()
{
    // clang-format off
    return
    {
      // new dummy::setup_fail::test_class(),
      // new dummy::test_fail::test_class(),
      // new dummy::cleanup_fail::test_class(),
      new qdb::blob_add_tag::test_class(),
      new qdb::blob_get::test_class(),
      new qdb::blob_get_noalloc::test_class(),
      new qdb::blob_put::test_class(),
      new qdb::blob_remove::test_class(),
      new qdb::blob_update::test_class(),
      new qdb::deque_pop_back::test_class(),
      new qdb::deque_pop_front::test_class(),
      new qdb::deque_push_back::test_class(),
      new qdb::deque_push_front::test_class(),
      new qdb::hset_contains::test_class(),
      new qdb::hset_erase::test_class(),
      new qdb::hset_insert::test_class(),
      new qdb::int_add::test_class(),
      new qdb::int_get::test_class(),
      new qdb::int_put::test_class(),
      new qdb::int_remove::test_class(),
      new qdb::int_update::test_class(),
      //new qdb::tag_add_blob::test_class(),
      new stdio::fread::test_class(),
      new stdio::fwrite::test_class(),
    };
}
<|endoftext|>


<commit_before>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/TriMesh.h"
#include "cinder/gl/gl.h"
#include "cinder/CameraUi.h"
#include "cinder/ObjLoader.h"
#include "cinder/Utilities.h"
#include "cinder/Filesystem.h"

using namespace ci;
using namespace ci::app;
using namespace std;

class MatCapShadersApp : public App {
  public:
	void setup() override;
	void mouseDown(MouseEvent event) override;
	void keyDown(KeyEvent event) override;
	void update() override;
	void draw() override;

  private:
    void setupCamera();
    void setupBatches();
	void setupTextures();
	void nextTexture();
	void prevTexture();

    // camera
    CameraPersp mCamera;
    CameraUi    mCameraUi;
    float       mVerticalFOV;
    float       mNearClip;
    float       mFarClip;
    vec3        mCamP;
    vec3        mCamTarget;
    vec3        mCamUp;

	// obj file batch
	TriMesh          mTriMesh;
	gl::BatchRef     mObjRef;
	gl::GlslProgRef  mMatcapGlsl;

	// wireframe grid batch
	geom::WirePlane  mGrid;
	gl::GlslProgRef  mGridGlsl;
	gl::BatchRef     mGridRef;

	// matcap textures
	gl::Texture2dRef mMatcapTex;
	vector<fs::path> mMatcapPaths;
	vector<fs::path>::iterator mCurrentPath;
};

void MatCapShadersApp::setup()
{
    setupCamera();
	setupTextures();
    setupBatches();
}

void MatCapShadersApp::setupCamera()
{
    mVerticalFOV = 50.f;
    mNearClip    = 0.05f;
    mFarClip     = 50.0f;
    mCamP        = vec3(0.68, 0.4, 0.48);
    mCamTarget   = vec3(0, 0.2, 0);
    mCamUp       = vec3(0, 1, 0);

    mCamera.setPerspective(mVerticalFOV, getWindowAspectRatio(), mNearClip, mFarClip);
    mCamera.lookAt(mCamP, mCamTarget, mCamUp);

    mCameraUi = CameraUi(&mCamera, getWindow());
}

void MatCapShadersApp::setupBatches()
{
    try
    {
        mMatcapGlsl = gl::GlslProg::create(loadAsset("shaders/matcap_vert.glsl"),
                                           loadAsset("shaders/matcap_frag.glsl"));
		mGridGlsl = gl::GlslProg::create(loadAsset("shaders/pass_thru_vert.glsl"),
			                             loadAsset("shaders/pass_thru_frag.glsl"));
    }
    catch (gl::GlslProgCompileExc e)
    {
        console() << e.what() << std::endl;
        quit();
    }

    ObjLoader loader(loadAsset("geo/skull2.obj"));
    mTriMesh = TriMesh(loader);
    mObjRef = gl::Batch::create(mTriMesh, mMatcapGlsl);

	mGrid = geom::WirePlane().subdivisions(ivec2(10, 10)).size(vec2(2, 2));
	mGridRef = gl::Batch::create(mGrid, mGridGlsl);
}

void MatCapShadersApp::setupTextures()
{
	// search assets for all .png files in sub directory /matcaps
	for (auto& p : fs::directory_iterator(getAssetPath("matcaps")))
	{
		if (!fs::is_regular_file(p))
			continue;

		if (p.path().extension().string().compare("png"))
				mMatcapPaths.push_back(p.path());
	}

	mCurrentPath = mMatcapPaths.begin();
	mMatcapTex = gl::Texture2d::create(loadImage(*mCurrentPath));
}

void MatCapShadersApp::nextTexture()
{
	if (mMatcapPaths.size() > 1) {

		mCurrentPath++;
		if (mCurrentPath == mMatcapPaths.end())
			mCurrentPath = mMatcapPaths.begin();

		try {
			mMatcapTex->update(Surface(loadImage(*mCurrentPath)));
		}
		catch (cinder::Exception e) {
			console() << e.what() << std::endl;
			quit();
		}
	}
}

void MatCapShadersApp::prevTexture()
{
	if (mMatcapPaths.size() > 1) {

		if (mCurrentPath == mMatcapPaths.begin())
			mCurrentPath = mMatcapPaths.end();
		mCurrentPath--;

		try {
			mMatcapTex->update(Surface(loadImage(*mCurrentPath)));
		}
		catch (cinder::Exception e) {
			console() << e.what() << std::endl;
			quit();
		}
	}
}

void MatCapShadersApp::mouseDown( MouseEvent event )
{
}

void MatCapShadersApp::keyDown( KeyEvent event )
{
	if (event.getChar() == 'x')
		nextTexture();
	else if (event.getChar() == 'z')
		prevTexture();
}

void MatCapShadersApp::update()
{
}

void MatCapShadersApp::draw()
{
	gl::enableDepthRead();
	gl::enableDepthWrite();

    gl::clear(Color::black());
    gl::color(1, 1, 1, 1);

    gl::setMatrices(mCamera);

	gl::ScopedTextureBind sTex(mMatcapTex);

	mGridRef->draw();
    mObjRef->draw();
}

CINDER_APP( MatCapShadersApp, RendererGl(RendererGl::Options().msaa(16)), [](App::Settings *settings) {
    settings->setMultiTouchEnabled(false);
    settings->setHighDensityDisplayEnabled(true);
    settings->setWindowSize(1280, 720);
	settings->setTitle("MatCapShaders - Z and X keys toggle matcaps");
    })
<commit_msg>Formatting<commit_after>#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/TriMesh.h"
#include "cinder/gl/gl.h"
#include "cinder/CameraUi.h"
#include "cinder/ObjLoader.h"
#include "cinder/Utilities.h"
#include "cinder/Filesystem.h"

using namespace ci;
using namespace ci::app;
using namespace std;

class MatCapShadersApp : public App {
  public:
    void setup() override;
    void mouseDown(MouseEvent event) override;
    void keyDown(KeyEvent event) override;
    void update() override;
    void draw() override;

  private:
    void setupCamera();
    void setupBatches();
    void setupTextures();
    void nextTexture();
    void prevTexture();

    // camera
    CameraPersp mCamera;
    CameraUi    mCameraUi;
    float       mVerticalFOV;
    float       mNearClip;
    float       mFarClip;
    vec3        mCamP;
    vec3        mCamTarget;
    vec3        mCamUp;

    // obj file batch
    TriMesh          mTriMesh;
    gl::BatchRef     mObjRef;
    gl::GlslProgRef  mMatcapGlsl;

    // wireframe grid batch
    geom::WirePlane  mGrid;
    gl::GlslProgRef  mGridGlsl;
    gl::BatchRef     mGridRef;

    // matcap textures
    gl::Texture2dRef mMatcapTex;
    vector<fs::path> mMatcapPaths;
    vector<fs::path>::iterator mCurrentPath;
};

void MatCapShadersApp::setup()
{
    setupCamera();
    setupTextures();
    setupBatches();
}

void MatCapShadersApp::setupCamera()
{
    mVerticalFOV = 50.f;
    mNearClip    = 0.05f;
    mFarClip     = 50.0f;
    mCamP        = vec3(0.68, 0.4, 0.48);
    mCamTarget   = vec3(0, 0.2, 0);
    mCamUp       = vec3(0, 1, 0);

    mCamera.setPerspective(mVerticalFOV, getWindowAspectRatio(), mNearClip, mFarClip);
    mCamera.lookAt(mCamP, mCamTarget, mCamUp);

    mCameraUi = CameraUi(&mCamera, getWindow());
}

void MatCapShadersApp::setupBatches()
{
    try
    {
        mMatcapGlsl = gl::GlslProg::create(loadAsset("shaders/matcap_vert.glsl"),
                                           loadAsset("shaders/matcap_frag.glsl"));
        mGridGlsl = gl::GlslProg::create(loadAsset("shaders/pass_thru_vert.glsl"),
                                         loadAsset("shaders/pass_thru_frag.glsl"));
    }
    catch (gl::GlslProgCompileExc e)
    {
        console() << e.what() << std::endl;
        quit();
    }

    ObjLoader loader(loadAsset("geo/skull2.obj"));
    mTriMesh = TriMesh(loader);
    mObjRef = gl::Batch::create(mTriMesh, mMatcapGlsl);

    mGrid = geom::WirePlane().subdivisions(ivec2(10, 10)).size(vec2(2, 2));
    mGridRef = gl::Batch::create(mGrid, mGridGlsl);
}

void MatCapShadersApp::setupTextures()
{
    // search assets for all .png files in sub directory /matcaps
    for (auto& p : fs::directory_iterator(getAssetPath("matcaps")))
    {
        if (!fs::is_regular_file(p))
            continue;

        if (p.path().extension().string().compare("png"))
                mMatcapPaths.push_back(p.path());
    }

    mCurrentPath = mMatcapPaths.begin();
    mMatcapTex = gl::Texture2d::create(loadImage(*mCurrentPath));
}

void MatCapShadersApp::nextTexture()
{
    if (mMatcapPaths.size() > 1) {

        mCurrentPath++;
        if (mCurrentPath == mMatcapPaths.end())
            mCurrentPath = mMatcapPaths.begin();

        try {
            mMatcapTex->update(Surface(loadImage(*mCurrentPath)));
        }
        catch (cinder::Exception e) {
            console() << e.what() << std::endl;
            quit();
        }
    }
}

void MatCapShadersApp::prevTexture()
{
    if (mMatcapPaths.size() > 1) {

        if (mCurrentPath == mMatcapPaths.begin())
            mCurrentPath = mMatcapPaths.end();
        mCurrentPath--;

        try {
            mMatcapTex->update(Surface(loadImage(*mCurrentPath)));
        }
        catch (cinder::Exception e) {
            console() << e.what() << std::endl;
            quit();
        }
    }
}

void MatCapShadersApp::mouseDown( MouseEvent event )
{
}

void MatCapShadersApp::keyDown( KeyEvent event )
{
    if (event.getChar() == 'x')
        nextTexture();
    else if (event.getChar() == 'z')
        prevTexture();
}

void MatCapShadersApp::update()
{
}

void MatCapShadersApp::draw()
{
    gl::enableDepthRead();
    gl::enableDepthWrite();

    gl::clear(Color::black());
    gl::color(1, 1, 1, 1);

    gl::setMatrices(mCamera);

    gl::ScopedTextureBind sTex(mMatcapTex);

    mGridRef->draw();
    mObjRef->draw();
}

CINDER_APP( MatCapShadersApp, RendererGl(RendererGl::Options().msaa(16)), [](App::Settings *settings) {
    settings->setMultiTouchEnabled(false);
    settings->setHighDensityDisplayEnabled(true);
    settings->setWindowSize(1280, 720);
    settings->setTitle("MatCapShaders - Z and X keys toggle matcaps");
    })
<|endoftext|>


<commit_before>#include <stdint.h>
#include "ndb_wrapper.h"
#include "../rcu.h"
#include "../varkey.h"
#include "../macros.h"

using namespace std;

void *
ndb_wrapper::new_txn(uint64_t txn_flags)
{
  switch (proto) {
  case PROTO_1:
    return new transaction_proto1(txn_flags);
  case PROTO_2:
    return new transaction_proto2(txn_flags);
  default:
    ALWAYS_ASSERT(false);
    return NULL;
  }
}

bool
ndb_wrapper::commit_txn(void *txn)
{
  bool ret;
  try {
    ret = ((transaction *) txn)->commit();
  } catch (transaction_abort_exception &ex) {
    ret = false;
  }
  delete (transaction *) txn;
  return ret;
}

void
ndb_wrapper::abort_txn(void *txn)
{
  ((transaction *) txn)->abort();
  delete (transaction *) txn;
}

abstract_ordered_index *
ndb_wrapper::open_index(const string &name)
{
  return new ndb_ordered_index;
}

void
ndb_wrapper::close_index(abstract_ordered_index *idx)
{
  delete idx;
}

bool
ndb_ordered_index::get(
    void *txn,
    const char *key, size_t keylen,
    char *&value, size_t &valuelen)
{
  try {
    txn_btree::value_type v = 0;
    bool ret = btr.search(*((transaction *) txn), varkey((const uint8_t *) key, keylen), v);
    if (!ret)
      return false;
    INVARIANT(v != NULL);
    size_t *sp = (size_t *) v;
    valuelen = *sp;
    value = (char *) malloc(valuelen);
    INVARIANT(value != NULL); // XXX: deal with this later
    memcpy(value, v + sizeof(size_t), valuelen);
    return true;
  } catch (transaction_abort_exception &ex) {
    throw abstract_db::abstract_abort_exception();
  }
}

const char *
ndb_ordered_index::put(
    void *txn,
    const char *key, size_t keylen,
    const char *value, size_t valuelen)
{
  uint8_t *record = new uint8_t[sizeof(size_t) + valuelen];
  size_t *sp = (size_t *) record;
  *sp = valuelen;
  memcpy(record + sizeof(size_t), value, valuelen);
  try {
    btr.insert(*((transaction *) txn), varkey((const uint8_t *) key, keylen), record);
  } catch (transaction_abort_exception &ex) {
    delete [] record;
    throw abstract_db::abstract_abort_exception();
  }
  return (const char *) record + sizeof(size_t);
}

class ndb_wrapper_search_range_callback : public txn_btree::search_range_callback {
public:
  ndb_wrapper_search_range_callback(ndb_ordered_index::scan_callback &upcall)
    : upcall(&upcall) {}

  virtual bool
  invoke(const txn_btree::key_type &k, txn_btree::value_type v)
  {
    const char *key = (const char *) k.data();
    const size_t keylen = k.size();

    const size_t *sp = (const size_t *) v;
    const size_t valuelen = *sp;
    const char *value = (const char *) (sp + 1);

    return upcall->invoke(key, keylen, value, valuelen);
  }

private:
  ndb_ordered_index::scan_callback *upcall;
};

void
ndb_ordered_index::scan(
    void *txn,
    const char *start_key, size_t start_len,
    const char *end_key, size_t end_len,
    bool has_end_key,
    scan_callback &callback)
{
  transaction &t = *((transaction *) txn);

  txn_btree::key_type lower((const uint8_t *) start_key, start_len);
  txn_btree::key_type upper((const uint8_t *) end_key, end_len);

  ndb_wrapper_search_range_callback c(callback);

  if (has_end_key)
    btr.search_range_call(t, lower, &upper, c);
  else
    btr.search_range_call(t, lower, NULL, c);
}

void
ndb_ordered_index::remove(
    void *txn,
    const char *key, size_t keylen)
{
  transaction &t = *((transaction *) txn);
  try {
    btr.remove(t, varkey((const uint8_t *) key, keylen));
  } catch (transaction_abort_exception &ex) {
    throw abstract_db::abstract_abort_exception();
  }
}

static void
record_cleanup_callback(uint8_t *record)
{
  INVARIANT(rcu::in_rcu_region());
  if (unlikely(!record))
    return;
  rcu::free_array(record);
}
NDB_TXN_REGISTER_CLEANUP_CALLBACK(record_cleanup_callback);
<commit_msg>catch and rethrow abort exception<commit_after>#include <stdint.h>
#include "ndb_wrapper.h"
#include "../rcu.h"
#include "../varkey.h"
#include "../macros.h"

using namespace std;

void *
ndb_wrapper::new_txn(uint64_t txn_flags)
{
  switch (proto) {
  case PROTO_1:
    return new transaction_proto1(txn_flags);
  case PROTO_2:
    return new transaction_proto2(txn_flags);
  default:
    ALWAYS_ASSERT(false);
    return NULL;
  }
}

bool
ndb_wrapper::commit_txn(void *txn)
{
  bool ret;
  try {
    ret = ((transaction *) txn)->commit();
  } catch (transaction_abort_exception &ex) {
    ret = false;
  }
  delete (transaction *) txn;
  return ret;
}

void
ndb_wrapper::abort_txn(void *txn)
{
  ((transaction *) txn)->abort();
  delete (transaction *) txn;
}

abstract_ordered_index *
ndb_wrapper::open_index(const string &name)
{
  return new ndb_ordered_index;
}

void
ndb_wrapper::close_index(abstract_ordered_index *idx)
{
  delete idx;
}

bool
ndb_ordered_index::get(
    void *txn,
    const char *key, size_t keylen,
    char *&value, size_t &valuelen)
{
  try {
    txn_btree::value_type v = 0;
    bool ret = btr.search(*((transaction *) txn), varkey((const uint8_t *) key, keylen), v);
    if (!ret)
      return false;
    INVARIANT(v != NULL);
    size_t *sp = (size_t *) v;
    valuelen = *sp;
    value = (char *) malloc(valuelen);
    INVARIANT(value != NULL); // XXX: deal with this later
    memcpy(value, v + sizeof(size_t), valuelen);
    return true;
  } catch (transaction_abort_exception &ex) {
    throw abstract_db::abstract_abort_exception();
  }
}

const char *
ndb_ordered_index::put(
    void *txn,
    const char *key, size_t keylen,
    const char *value, size_t valuelen)
{
  uint8_t *record = new uint8_t[sizeof(size_t) + valuelen];
  size_t *sp = (size_t *) record;
  *sp = valuelen;
  memcpy(record + sizeof(size_t), value, valuelen);
  try {
    btr.insert(*((transaction *) txn), varkey((const uint8_t *) key, keylen), record);
  } catch (transaction_abort_exception &ex) {
    delete [] record;
    throw abstract_db::abstract_abort_exception();
  }
  return (const char *) record + sizeof(size_t);
}

class ndb_wrapper_search_range_callback : public txn_btree::search_range_callback {
public:
  ndb_wrapper_search_range_callback(ndb_ordered_index::scan_callback &upcall)
    : upcall(&upcall) {}

  virtual bool
  invoke(const txn_btree::key_type &k, txn_btree::value_type v)
  {
    const char *key = (const char *) k.data();
    const size_t keylen = k.size();

    const size_t *sp = (const size_t *) v;
    const size_t valuelen = *sp;
    const char *value = (const char *) (sp + 1);

    return upcall->invoke(key, keylen, value, valuelen);
  }

private:
  ndb_ordered_index::scan_callback *upcall;
};

void
ndb_ordered_index::scan(
    void *txn,
    const char *start_key, size_t start_len,
    const char *end_key, size_t end_len,
    bool has_end_key,
    scan_callback &callback)
{
  transaction &t = *((transaction *) txn);

  txn_btree::key_type lower((const uint8_t *) start_key, start_len);
  txn_btree::key_type upper((const uint8_t *) end_key, end_len);

  ndb_wrapper_search_range_callback c(callback);

  try {
    if (has_end_key)
      btr.search_range_call(t, lower, &upper, c);
    else
      btr.search_range_call(t, lower, NULL, c);
  } catch (transaction_abort_exception &ex) {
    throw abstract_db::abstract_abort_exception();
  }
}

void
ndb_ordered_index::remove(
    void *txn,
    const char *key, size_t keylen)
{
  transaction &t = *((transaction *) txn);
  try {
    btr.remove(t, varkey((const uint8_t *) key, keylen));
  } catch (transaction_abort_exception &ex) {
    throw abstract_db::abstract_abort_exception();
  }
}

static void
record_cleanup_callback(uint8_t *record)
{
  INVARIANT(rcu::in_rcu_region());
  if (unlikely(!record))
    return;
  rcu::free_array(record);
}
NDB_TXN_REGISTER_CLEANUP_CALLBACK(record_cleanup_callback);
<|endoftext|>


<commit_before>//=====================================================================//
/*!	@file
	@brief	ＰＷＭ出力サンプル
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include "common/port_utils.hpp"
#include "common/tau_io.hpp"

namespace {
	void wait_()
	{
		asm("nop");
	}

	typedef device::tau_io<device::TAU00> master;
	master master_;
	device::tau_io<device::TAU01> pwm_;

	bool init_pwm_()
	{
		uint8_t intr_level = 0;
		if(!master_.start_interval(100000, intr_level)) {
			return false;
		}
		if(!pwm_.start_pwm<master::tau_type>(0, intr_level)) {
			return false;
		}
		return true;
	}
}

int main(int argc, char* argv[])
{
	utils::port::pullup_all();  ///< 安全の為、全ての入力をプルアップ

	device::PM4.B3 = 0;  // output

	uint32_t speed = 1000000;
	{
		if(!init_pwm_()) {
			speed /= 15;
		}
	}

	auto val = master_.get_value();  // マスターチャネルのカウント最大値
	pwm_.set_value(val / 4);  // PWM Duty 25%

	bool f = false;
	while(1) {
		for(uint32_t i = 0; i < speed; ++i) {
			wait_();
		}
		device::P4.B3 = f;
		f = !f;
	}
}
<commit_msg>update comment<commit_after>//=====================================================================//
/*!	@file
	@brief	ＰＷＭ出力サンプル @n
			TO01(P1-6) から、１００ＫＨｚ、２５％ディーティーの波形出力
	@author	平松邦仁 (hira@rvf-rc45.net)
*/
//=====================================================================//
#include <cstdint>
#include "common/port_utils.hpp"
#include "common/tau_io.hpp"

namespace {
	void wait_()
	{
		asm("nop");
	}

	typedef device::tau_io<device::TAU00> master;
	master master_;
	device::tau_io<device::TAU01> pwm_;

	bool init_pwm_()
	{
		uint8_t intr_level = 0;
		if(!master_.start_interval(100000, intr_level)) {
			return false;
		}
		if(!pwm_.start_pwm<master::tau_type>(0, intr_level)) {
			return false;
		}
		return true;
	}
}

int main(int argc, char* argv[])
{
	utils::port::pullup_all();  ///< 安全の為、全ての入力をプルアップ

	device::PM4.B3 = 0;  // output

	uint32_t speed = 1000000;
	{
		if(!init_pwm_()) {
			speed /= 15;
		}
	}

	auto val = master_.get_value();  // マスターチャネルのカウント最大値
	pwm_.set_value(val / 4);  // PWM Duty 25%

	bool f = false;
	while(1) {
		for(uint32_t i = 0; i < speed; ++i) {
			wait_();
		}
		device::P4.B3 = f;
		f = !f;
	}
}
<|endoftext|>


<commit_before>//
// message_update.hpp
// ******************
//
// Copyright (c) 2018 Sharon W (sharon at aegis dot gg)
//
// Distributed under the MIT License. (See accompanying file LICENSE)
//

#pragma once

#include "aegis/config.hpp"
#include "aegis/snowflake.hpp"
#include "aegis/objects/message.hpp"
#include "aegis/fwd.hpp"
#include <string>
#include <vector>

namespace aegis
{

namespace gateway
{

namespace events
{

/**\todo Needs documentation
 */
struct message_update
{
    objects::message msg; /**<\todo Needs documentation */
#if !defined(AEGIS_DISABLE_ALL_CACHE)
    message_update(const json & j, channel * c, member * m) : msg(j), _channel(c), _member(m) {};
    shards::shard * _shard; /**< Pointer to shard object this message came from */
    core * bot; /**< Pointer to the main bot object */
    channel * const _channel; /**<\todo Needs documentation */
    member * const _member; /**<\todo Needs documentation */
#else
    message_update(shards::shard * _s, const json & j) : base_event(_s), msg(j) {};
#endif
};

/**\todo Needs documentation
 */
inline void from_json(const nlohmann::json& j, message_update& m)
{
    m.msg = j;
}

}

}

}
<commit_msg>Missing fix of message_update object<commit_after>//
// message_update.hpp
// ******************
//
// Copyright (c) 2018 Sharon W (sharon at aegis dot gg)
//
// Distributed under the MIT License. (See accompanying file LICENSE)
//

#pragma once

#include "aegis/config.hpp"
#include "aegis/snowflake.hpp"
#include "aegis/objects/message.hpp"
#include "aegis/fwd.hpp"
#include <string>
#include <vector>

namespace aegis
{

namespace gateway
{

namespace events
{

/**\todo Needs documentation
 */
struct message_update
{
    objects::message msg; /**<\todo Needs documentation */
#if !defined(AEGIS_DISABLE_ALL_CACHE)
    message_update(const json & j, channel * c, member * m) : msg(j), _channel(c), _member(m) {};
    shards::shard * _shard; /**< Pointer to shard object this message came from */
    core * bot; /**< Pointer to the main bot object */
    channel * const _channel; /**<\todo Needs documentation */
    member * const _member; /**<\todo Needs documentation */
#else
    message_update(const json & j) : msg(j) {};
#endif
};

/**\todo Needs documentation
 */
inline void from_json(const nlohmann::json& j, message_update& m)
{
    m.msg = j;
}

}

}

}
<|endoftext|>