<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2007 Jos van den Oever <jos@vandenoever.info>
 * Copyright (C) 2007 Flavio Castelli <flavio.castelli@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "filelister.h"
#include "strigiconfig.h"
#include "strigi_thread.h"
#include "analyzerconfiguration.h"
#include <set>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstdlib>
#include <cstring>
#include "stgdirent.h" //dirent replacement (includes native if available)

#ifdef HAVE_DIRECT_H
#include <direct.h>
#endif
#include <errno.h>

using namespace std;
using namespace Strigi;

string fixPath (string path)
{
    if ( path.c_str() == NULL || path.length() == 0 )
        return "";

    string temp(path);

#ifdef HAVE_WINDOWS_H
    size_t l= temp.length();
    char* t = (char*)temp.c_str();
    for (size_t i=0;i<l;i++){
        if ( t[i] == '\\' )
            t[i] = '/';
    }
    temp[0] = tolower(temp.at(0));
#endif

    char separator = '/';

    if (temp[temp.length() - 1 ] != separator)
        temp += separator;

    return temp;
}

class FileLister::Private {
public:
    char path[10000];
    STRIGI_MUTEX_DEFINE(mutex);
    DIR** dirs;
    DIR** dirsEnd;
    DIR** curDir;
    int* len;
    int* lenEnd;
    int* curLen;
    time_t mtime;
    struct dirent* subdir;
    struct stat dirstat;
    set<string> listedDirs;
    const AnalyzerConfiguration* const config;

    Private(const AnalyzerConfiguration* ic);
    ~Private();
    int nextFile(string& p, time_t& time) {
        int r;
        STRIGI_MUTEX_LOCK(&mutex);
        r = nextFile();
        if (r > 0) {
            p.assign(path, r);
            time = mtime;
        }
        STRIGI_MUTEX_UNLOCK(&mutex);
        return r;
    }
    void startListing(const std::string&);
    int nextFile();
};
FileLister::Private::Private(
            const AnalyzerConfiguration* ic) :
        config(ic) {
    STRIGI_MUTEX_INIT(&mutex);
    int nOpenDirs = 100;
    dirs = (DIR**)malloc(sizeof(DIR*)*nOpenDirs);
    dirsEnd = dirs + nOpenDirs;
    len = (int*)malloc(sizeof(int)*nOpenDirs);
    lenEnd = len + nOpenDirs;
    curDir = dirs - 1;
}
void
FileLister::Private::startListing(const string& dir){
    listedDirs.clear();
    curDir = dirs;
    curLen = len;
    int len = dir.length();
    *curLen = len;
    strcpy(path, dir.c_str());
    if (len) {
        if (path[len-1] != '/') {
            path[len++] = '/';
            path[len] = 0;
            *curLen = len;
        }
        DIR* d = opendir(path);
        if (d) {
            *curDir = d;
            listedDirs.insert (path);
        } else {
            curDir--;
        }
    } else {
        curDir--;
    }
}
FileLister::Private::~Private() {
    while (curDir >= dirs) {
        if (*curDir) {
            closedir(*curDir);
        }
        curDir--;
    }
    free(dirs);
    free(len);
    STRIGI_MUTEX_DESTROY(&mutex);
}
int
FileLister::Private::nextFile() {

    while (curDir >= dirs) {
        DIR* dir = *curDir;
        int l = *curLen;
        subdir = readdir(dir);
        while (subdir) {
            // skip the directories '.' and '..'
            char c1 = subdir->d_name[0];
            if (c1 == '.') {
                char c2 = subdir->d_name[1];
                if (c2 == '.' || c2 == '\0') {
                    subdir = readdir(dir);
                    continue;
                }
            }
            strcpy(path + l, subdir->d_name);
            int sl = l + strlen(subdir->d_name);
#ifdef _WIN32
            // windows does not have symbolic links, so stat() is fine
            if (stat(path, &dirstat) == 0) {
#else
            if (lstat(path, &dirstat) == 0) {
#endif
                if (S_ISREG(dirstat.st_mode)) {
                    if (config == 0 || config->indexFile(path, path+sl)) {
                        mtime = dirstat.st_mtime;
                        return sl;
                    }
                } else if (dirstat.st_mode & S_IFDIR && (config == 0
                        || config->indexDir(path, path+sl))) {
                    mtime = dirstat.st_mtime;
                    strcpy(this->path+sl, "/");
                    DIR* d = opendir(path);
                    if (d) {
                        curDir++;
                        curLen++;
                        dir = *curDir = d;
                        l = *curLen = sl+1;
                        listedDirs.insert ( path);
                    }
                }
            }
            subdir = readdir(dir);
        }
        closedir(dir);
        curDir--;
        curLen--;
    }
    return -1;
}
FileLister::FileLister(const AnalyzerConfiguration* ic)
    : p(new Private(ic)) {
}
FileLister::~FileLister() {
    delete p;
}
void
FileLister::startListing(const string& dir) {
    p->startListing(dir);
}
int
FileLister::nextFile(std::string& path, time_t& time) {
    return p->nextFile(path, time);
}
int
FileLister::nextFile(const char*& path, time_t& time) {
    int r = p->nextFile();
    if (r >= 0) {
        time = p->mtime;
        path = p->path;
    }
    return r;
}
void
FileLister::skipTillAfter(const std::string& lastToSkip) {
    int r = p->nextFile();
    while (r >= 0 && p->path != lastToSkip) {
        r = p->nextFile();
    }
}
set<string>&
FileLister::getListedDirs()
{
    return p->listedDirs;
}
<commit_msg>fix file and dir name matching<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2007 Jos van den Oever <jos@vandenoever.info>
 * Copyright (C) 2007 Flavio Castelli <flavio.castelli@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "filelister.h"
#include "strigiconfig.h"
#include "strigi_thread.h"
#include "analyzerconfiguration.h"
#include <set>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstdlib>
#include <cstring>
#include "stgdirent.h" //dirent replacement (includes native if available)

#ifdef HAVE_DIRECT_H
#include <direct.h>
#endif
#include <errno.h>

using namespace std;
using namespace Strigi;

string fixPath (string path)
{
    if ( path.c_str() == NULL || path.length() == 0 )
        return "";

    string temp(path);

#ifdef HAVE_WINDOWS_H
    size_t l= temp.length();
    char* t = (char*)temp.c_str();
    for (size_t i=0;i<l;i++){
        if ( t[i] == '\\' )
            t[i] = '/';
    }
    temp[0] = tolower(temp.at(0));
#endif

    char separator = '/';

    if (temp[temp.length() - 1 ] != separator)
        temp += separator;

    return temp;
}

class FileLister::Private {
public:
    char path[10000];
    STRIGI_MUTEX_DEFINE(mutex);
    DIR** dirs;
    DIR** dirsEnd;
    DIR** curDir;
    int* len;
    int* lenEnd;
    int* curLen;
    time_t mtime;
    struct dirent* subdir;
    struct stat dirstat;
    set<string> listedDirs;
    const AnalyzerConfiguration* const config;

    Private(const AnalyzerConfiguration* ic);
    ~Private();
    int nextFile(string& p, time_t& time) {
        int r;
        STRIGI_MUTEX_LOCK(&mutex);
        r = nextFile();
        if (r > 0) {
            p.assign(path, r);
            time = mtime;
        }
        STRIGI_MUTEX_UNLOCK(&mutex);
        return r;
    }
    void startListing(const std::string&);
    int nextFile();
};
FileLister::Private::Private(
            const AnalyzerConfiguration* ic) :
        config(ic) {
    STRIGI_MUTEX_INIT(&mutex);
    int nOpenDirs = 100;
    dirs = (DIR**)malloc(sizeof(DIR*)*nOpenDirs);
    dirsEnd = dirs + nOpenDirs;
    len = (int*)malloc(sizeof(int)*nOpenDirs);
    lenEnd = len + nOpenDirs;
    curDir = dirs - 1;
}
void
FileLister::Private::startListing(const string& dir){
    listedDirs.clear();
    curDir = dirs;
    curLen = len;
    int len = dir.length();
    *curLen = len;
    strcpy(path, dir.c_str());
    if (len) {
        if (path[len-1] != '/') {
            path[len++] = '/';
            path[len] = 0;
            *curLen = len;
        }
        DIR* d = opendir(path);
        if (d) {
            *curDir = d;
            listedDirs.insert (path);
        } else {
            curDir--;
        }
    } else {
        curDir--;
    }
}
FileLister::Private::~Private() {
    while (curDir >= dirs) {
        if (*curDir) {
            closedir(*curDir);
        }
        curDir--;
    }
    free(dirs);
    free(len);
    STRIGI_MUTEX_DESTROY(&mutex);
}
int
FileLister::Private::nextFile() {

    while (curDir >= dirs) {
        DIR* dir = *curDir;
        int l = *curLen;
        subdir = readdir(dir);
        while (subdir) {
            // skip the directories '.' and '..'
            char c1 = subdir->d_name[0];
            if (c1 == '.') {
                char c2 = subdir->d_name[1];
                if (c2 == '.' || c2 == '\0') {
                    subdir = readdir(dir);
                    continue;
                }
            }
            strcpy(path + l, subdir->d_name);
            int sl = l + strlen(subdir->d_name);
#ifdef _WIN32
            // windows does not have symbolic links, so stat() is fine
            if (stat(path, &dirstat) == 0) {
#else
            if (lstat(path, &dirstat) == 0) {
#endif
                if (S_ISREG(dirstat.st_mode)) {
                    if (config == 0 || config->indexFile(path, path+l)) {
                        mtime = dirstat.st_mtime;
                        return sl;
                    }
                } else if (dirstat.st_mode & S_IFDIR && (config == 0
                        || config->indexDir(path, path+l))) {
                    mtime = dirstat.st_mtime;
                    strcpy(this->path+sl, "/");
                    DIR* d = opendir(path);
                    if (d) {
                        curDir++;
                        curLen++;
                        dir = *curDir = d;
                        l = *curLen = sl+1;
                        listedDirs.insert ( path);
                    }
                }
            }
            subdir = readdir(dir);
        }
        closedir(dir);
        curDir--;
        curLen--;
    }
    return -1;
}
FileLister::FileLister(const AnalyzerConfiguration* ic)
    : p(new Private(ic)) {
}
FileLister::~FileLister() {
    delete p;
}
void
FileLister::startListing(const string& dir) {
    p->startListing(dir);
}
int
FileLister::nextFile(std::string& path, time_t& time) {
    return p->nextFile(path, time);
}
int
FileLister::nextFile(const char*& path, time_t& time) {
    int r = p->nextFile();
    if (r >= 0) {
        time = p->mtime;
        path = p->path;
    }
    return r;
}
void
FileLister::skipTillAfter(const std::string& lastToSkip) {
    int r = p->nextFile();
    while (r >= 0 && p->path != lastToSkip) {
        r = p->nextFile();
    }
}
set<string>&
FileLister::getListedDirs()
{
    return p->listedDirs;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/// \file libuobject/main.cc

#include <libport/cerrno>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/unistd.h>

#include <iostream>
#include <list>
#include <sstream>

#include <libport/debug.hh>
#include <libport/cli.hh>
#include <libport/containers.hh>
#include <libport/foreach.hh>
#include <libport/lexical-cast.hh>
#include <libport/package-info.hh>
#include <libport/program-name.hh>
#include <libport/sysexits.hh>

#include <urbi/package-info.hh>
#include <urbi/uexternal.hh>
#include <urbi/umain.hh>
#include <urbi/umessage.hh>
#include <urbi/uobject.hh>
#include <urbi/urbi-root.hh>
#include <urbi/usyncclient.hh>
#include <libuobject/remote-ucontext-impl.hh>
using libport::program_name;

GD_CATEGORY(UrbiLaunch);

namespace urbi
{
  static impl::RemoteUContextImpl* defaultContext;

  static
  UCallbackAction
  debug(const UMessage& msg)
  {
    GD_SWARN("unexpected message: " << msg);
    return URBI_CONTINUE;
  }

  static
  UCallbackAction
  endProgram(const UMessage& msg)
  {
    GD_SWARN("got a disconnection message: " << msg);
    exit(0);
    return URBI_CONTINUE; //stupid gcc
  }

  static
  void
  usage()
  {
    std::cout <<
      "usage:\n" << libport::program_name() << " [OPTION]...\n"
      "\n"
      "Options:\n"
      "  -b, --buffer SIZE     input buffer size"
		 << " [" << UAbstractClient::URBI_BUFLEN << "]\n"
      "  -h, --help            display this message and exit\n"
      "  -H, --host ADDR       server host name"
                 << " [" << UClient::default_host() << "]\n"
      "      --server          put remote in server mode\n"
      "      --no-sync-client  Use UClient instead of USyncClient\n"
      "  -p, --port PORT       tcp port URBI will listen to"
		 << " [" << UAbstractClient::URBI_PORT << "]\n"
      "  -r, --port-file FILE  file containing the port to listen to\n"
      "  -V, --version         print version information and exit\n"
      "  -d, --disconnect      exit program if disconnected(defaults)\n"
      "  -s, --stay-alive      do not exit program if disconnected\n"
      "  --describe            describe loaded UObjects and exit\n"
      "  --describe-file FILE  write the list of present UObjects to FILE\n"
		 << libport::exit (EX_OK);
  }

  static
  void
  version()
  {
    std::cout << urbi::package_info() << std::endl
              << libport::exit (EX_OK);
  }

  typedef std::vector<std::string> files_type;
  int
  initialize(const std::string& host, int port, size_t buflen,
	     bool exitOnDisconnect, bool server, const files_type& files,
             bool useSyncClient)
  {
    GD_FINFO_TRACE("this is %s", program_name());
    GD_SINFO_TRACE(urbi::package_info());
    GD_FINFO_TRACE("remote component running on %s:%s", host, port);
    if (useSyncClient)
    {
      USyncClient::options o;
      o.server(server);
      new USyncClient(host, port, buflen, o);
    }
    else
    {
      GD_WARN("the no-sync-client mode is dangerous.  "
              "Any attempt to use synchronous operation will crash"
              " your program.");
      UClient::options o;
      o.server(server);
      setDefaultClient(new UClient(host, port, buflen, o));
    }
    if (exitOnDisconnect)
    {
      if (!getDefaultClient() || getDefaultClient()->error())
	std::cerr << "ERROR: failed to connect, exiting..." << std::endl
		  << libport::exit(1);
      getDefaultClient()->setClientErrorCallback(callback(&endProgram));
    }
    if (!getDefaultClient() || getDefaultClient()->error())
      return 1;

#ifdef LIBURBIDEBUG
    getDefaultClient()->setWildcardCallback(callback(&debug));
#else
    getDefaultClient()->setErrorCallback(callback(&debug));
#endif

    // Wait for client to be connected if in server mode.
    while (getDefaultClient()
           && !getDefaultClient()->error()
           && !getDefaultClient()->isConnected())
      usleep(20000);

    defaultContext = new impl::RemoteUContextImpl(
      (USyncClient*)dynamic_cast<UClient*>(getDefaultClient()));
    // Waiting for connectionID.
    while (getDefaultClient()
           && getDefaultClient()->connectionID() == "")
      usleep(5000);
    // Initialize in the correct thread.
    getDefaultClient()->notifyCallbacks
      (UMessage(*getDefaultClient(), 0, externalModuleTag,
                libport::format("[%s]", UEM_INIT)));
    // Load initialization files.
    foreach (const std::string& file, files)
      getDefaultClient()->sendFile(file);
    return 0;
  }

  namespace
  {
    static
    void
    argument_with_option(const char* longopt,
                         char shortopt,
                         const std::string& val)
    {
      std::cerr
        << program_name()
        << ": warning: arguments without options are deprecated"
        << std::endl
        << "use `-" << shortopt << ' ' << val << '\''
        << " or `--" << longopt << ' ' << val << "' instead"
        << std::endl
        << "Try `" << program_name() << " --help' for more information."
        << std::endl;
    }

  }

  URBI_SDK_API int
  main(const libport::cli_args_type& args, UrbiRoot&, bool block, bool)
  {
    GD_INIT();

    std::string host = UClient::default_host();
    bool exitOnDisconnect = true;
    int port = UAbstractClient::URBI_PORT;
    bool server = false;
    bool useSyncClient = true;
    bool describeMode = false;
    std::string describeFile;
    size_t buflen = UAbstractClient::URBI_BUFLEN;
    // Files to load
    files_type files;

    // The number of the next (non-option) argument.
    unsigned argp = 1;
    for (unsigned i = 1; i < args.size(); ++i)
    {
      const std::string& arg = args[i];
      if (arg == "--buffer" || arg == "-b")
	buflen = libport::convert_argument<size_t>(args, i++);
      else if (arg == "--disconnect" || arg == "-d")
	exitOnDisconnect = true;
      else if (arg == "--file" || arg == "-f")
        files.push_back(libport::convert_argument<const char*>(args, i++));
      else if (arg == "--stay-alive" || arg == "-s")
	exitOnDisconnect = false;
      else if (arg == "--help" || arg == "-h")
	usage();
      else if (arg == "--host" || arg == "-H")
	host = libport::convert_argument<std::string>(args, i++);
      else if (arg == "--no-sync-client")
        useSyncClient = false;
      else if (arg == "--port" || arg == "-p")
	port = libport::convert_argument<unsigned>(args, i++);
      else if (arg == "--port-file" || arg == "-r")
	port =
          (libport::file_contents_get<int>
           (libport::convert_argument<const char*>(args, i++)));
      else if (arg == "--server")
	server = true;
      // FIXME: Remove -v some day.
      else if (arg == "--version" || arg == "-V" || arg == "-v")
	version();
      else if (arg == "--describe")
	describeMode = true;
      else if (arg == "--describe-file")
         describeFile = libport::convert_argument<const char*>(args, i++);
      else if (arg[0] == '-')
	libport::invalid_option(arg);
      else
	// A genuine argument.
	switch (argp++)
	{
	  case 1:
            argument_with_option("host", 'H', args[i]);
	    host = args[i];
	    break;
	  case 2:
            argument_with_option("port", 'p', args[i]);
	    port = libport::convert_argument<unsigned>("port", args[i]);
	    break;
	  default:
	    std::cerr << "unexpected argument: " << arg << std::endl
		      << libport::exit(EX_USAGE);
	}
    }

    if (describeMode)
    {
      foreach(baseURBIStarter* s, baseURBIStarter::list())
        std::cout << s->name << std::endl;
      foreach(baseURBIStarterHub* s, baseURBIStarterHub::list())
        std::cout << s->name << std::endl;
      return 0;
    }
    if (!describeFile.empty())
    {
      std::ofstream of(describeFile.c_str());
      foreach(baseURBIStarter* s, baseURBIStarter::list())
        of << s->name << std::endl;
      foreach(baseURBIStarterHub* s, baseURBIStarterHub::list())
        of << s->name << std::endl;
    }
    initialize(host, port, buflen, exitOnDisconnect, server, files,
               useSyncClient);

    if (block)
      while (true)
        usleep(30000000);
    return 0;
  }

}
<commit_msg>remote-main: Properly wait for backend initialization.<commit_after>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/// \file libuobject/main.cc

#include <libport/cerrno>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/unistd.h>

#include <iostream>
#include <list>
#include <sstream>

#include <libport/debug.hh>
#include <libport/cli.hh>
#include <libport/containers.hh>
#include <libport/foreach.hh>
#include <libport/lexical-cast.hh>
#include <libport/package-info.hh>
#include <libport/program-name.hh>
#include <libport/sysexits.hh>

#include <urbi/package-info.hh>
#include <urbi/uexternal.hh>
#include <urbi/umain.hh>
#include <urbi/umessage.hh>
#include <urbi/uobject.hh>
#include <urbi/urbi-root.hh>
#include <urbi/usyncclient.hh>
#include <libuobject/remote-ucontext-impl.hh>
using libport::program_name;

GD_CATEGORY(UrbiLaunch);

namespace urbi
{
  static impl::RemoteUContextImpl* defaultContext;

  static
  UCallbackAction
  debug(const UMessage& msg)
  {
    GD_SWARN("unexpected message: " << msg);
    return URBI_CONTINUE;
  }

  static
  UCallbackAction
  endProgram(const UMessage& msg)
  {
    GD_SWARN("got a disconnection message: " << msg);
    exit(0);
    return URBI_CONTINUE; //stupid gcc
  }

  static
  void
  usage()
  {
    std::cout <<
      "usage:\n" << libport::program_name() << " [OPTION]...\n"
      "\n"
      "Options:\n"
      "  -b, --buffer SIZE     input buffer size"
		 << " [" << UAbstractClient::URBI_BUFLEN << "]\n"
      "  -h, --help            display this message and exit\n"
      "  -H, --host ADDR       server host name"
                 << " [" << UClient::default_host() << "]\n"
      "      --server          put remote in server mode\n"
      "      --no-sync-client  Use UClient instead of USyncClient\n"
      "  -p, --port PORT       tcp port URBI will listen to"
		 << " [" << UAbstractClient::URBI_PORT << "]\n"
      "  -r, --port-file FILE  file containing the port to listen to\n"
      "  -V, --version         print version information and exit\n"
      "  -d, --disconnect      exit program if disconnected(defaults)\n"
      "  -s, --stay-alive      do not exit program if disconnected\n"
      "  --describe            describe loaded UObjects and exit\n"
      "  --describe-file FILE  write the list of present UObjects to FILE\n"
		 << libport::exit (EX_OK);
  }

  static
  void
  version()
  {
    std::cout << urbi::package_info() << std::endl
              << libport::exit (EX_OK);
  }

  typedef std::vector<std::string> files_type;
  int
  initialize(const std::string& host, int port, size_t buflen,
	     bool exitOnDisconnect, bool server, const files_type& files,
             bool useSyncClient)
  {
    GD_FINFO_TRACE("this is %s", program_name());
    GD_SINFO_TRACE(urbi::package_info());
    GD_FINFO_TRACE("remote component running on %s:%s", host, port);
    if (useSyncClient)
    {
      USyncClient::options o;
      o.server(server);
      new USyncClient(host, port, buflen, o);
    }
    else
    {
      GD_WARN("the no-sync-client mode is dangerous.  "
              "Any attempt to use synchronous operation will crash"
              " your program.");
      UClient::options o;
      o.server(server);
      setDefaultClient(new UClient(host, port, buflen, o));
    }
    if (exitOnDisconnect)
    {
      if (!getDefaultClient() || getDefaultClient()->error())
	std::cerr << "ERROR: failed to connect, exiting..." << std::endl
		  << libport::exit(1);
      getDefaultClient()->setClientErrorCallback(callback(&endProgram));
    }
    if (!getDefaultClient() || getDefaultClient()->error())
      return 1;

#ifdef LIBURBIDEBUG
    getDefaultClient()->setWildcardCallback(callback(&debug));
#else
    getDefaultClient()->setErrorCallback(callback(&debug));
#endif

    // Wait for client to be connected if in server mode.
    // Also wait for initialization exchanges.
    while (getDefaultClient()
           && !getDefaultClient()->error()
           && !getDefaultClient()->isConnected()
	   && getDefaultClient()->connectionID() == "")
      usleep(20000);

    defaultContext = new impl::RemoteUContextImpl(
      (USyncClient*)dynamic_cast<UClient*>(getDefaultClient()));

    // Initialize in the correct thread.
    getDefaultClient()->notifyCallbacks
      (UMessage(*getDefaultClient(), 0, externalModuleTag,
                libport::format("[%s]", UEM_INIT)));
    // Load initialization files.
    foreach (const std::string& file, files)
      getDefaultClient()->sendFile(file);
    return 0;
  }

  namespace
  {
    static
    void
    argument_with_option(const char* longopt,
                         char shortopt,
                         const std::string& val)
    {
      std::cerr
        << program_name()
        << ": warning: arguments without options are deprecated"
        << std::endl
        << "use `-" << shortopt << ' ' << val << '\''
        << " or `--" << longopt << ' ' << val << "' instead"
        << std::endl
        << "Try `" << program_name() << " --help' for more information."
        << std::endl;
    }

  }

  URBI_SDK_API int
  main(const libport::cli_args_type& args, UrbiRoot&, bool block, bool)
  {
    GD_INIT();

    std::string host = UClient::default_host();
    bool exitOnDisconnect = true;
    int port = UAbstractClient::URBI_PORT;
    bool server = false;
    bool useSyncClient = true;
    bool describeMode = false;
    std::string describeFile;
    size_t buflen = UAbstractClient::URBI_BUFLEN;
    // Files to load
    files_type files;

    // The number of the next (non-option) argument.
    unsigned argp = 1;
    for (unsigned i = 1; i < args.size(); ++i)
    {
      const std::string& arg = args[i];
      if (arg == "--buffer" || arg == "-b")
	buflen = libport::convert_argument<size_t>(args, i++);
      else if (arg == "--disconnect" || arg == "-d")
	exitOnDisconnect = true;
      else if (arg == "--file" || arg == "-f")
        files.push_back(libport::convert_argument<const char*>(args, i++));
      else if (arg == "--stay-alive" || arg == "-s")
	exitOnDisconnect = false;
      else if (arg == "--help" || arg == "-h")
	usage();
      else if (arg == "--host" || arg == "-H")
	host = libport::convert_argument<std::string>(args, i++);
      else if (arg == "--no-sync-client")
        useSyncClient = false;
      else if (arg == "--port" || arg == "-p")
	port = libport::convert_argument<unsigned>(args, i++);
      else if (arg == "--port-file" || arg == "-r")
	port =
          (libport::file_contents_get<int>
           (libport::convert_argument<const char*>(args, i++)));
      else if (arg == "--server")
	server = true;
      // FIXME: Remove -v some day.
      else if (arg == "--version" || arg == "-V" || arg == "-v")
	version();
      else if (arg == "--describe")
	describeMode = true;
      else if (arg == "--describe-file")
         describeFile = libport::convert_argument<const char*>(args, i++);
      else if (arg[0] == '-')
	libport::invalid_option(arg);
      else
	// A genuine argument.
	switch (argp++)
	{
	  case 1:
            argument_with_option("host", 'H', args[i]);
	    host = args[i];
	    break;
	  case 2:
            argument_with_option("port", 'p', args[i]);
	    port = libport::convert_argument<unsigned>("port", args[i]);
	    break;
	  default:
	    std::cerr << "unexpected argument: " << arg << std::endl
		      << libport::exit(EX_USAGE);
	}
    }

    if (describeMode)
    {
      foreach(baseURBIStarter* s, baseURBIStarter::list())
        std::cout << s->name << std::endl;
      foreach(baseURBIStarterHub* s, baseURBIStarterHub::list())
        std::cout << s->name << std::endl;
      return 0;
    }
    if (!describeFile.empty())
    {
      std::ofstream of(describeFile.c_str());
      foreach(baseURBIStarter* s, baseURBIStarter::list())
        of << s->name << std::endl;
      foreach(baseURBIStarterHub* s, baseURBIStarterHub::list())
        of << s->name << std::endl;
    }
    initialize(host, port, buflen, exitOnDisconnect, server, files,
               useSyncClient);

    if (block)
      while (true)
        usleep(30000000);
    return 0;
  }

}
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "base64inputstream.h"

#include <cstring>

using namespace std;
using namespace Strigi;

/* code is based on public domain code at
   http://www.tug.org/ftp/vm/base64-decode.c
*/

class Base64InputStream::Private {
public:
    Base64InputStream* const p;
    InputStream* input;
    const char* pos, * pend;
    int32_t bits;
    int32_t nleft;
    char bytestodo;
    char char_count;

    Private(Base64InputStream* p, InputStream* i);
    bool moreData();
    int32_t fillBuffer(char* start, int32_t space);
};

const unsigned char alphabet[]
    = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
bool inalphabet[256];
unsigned char decoder[133];
bool initializedAlphabet = false;
void initialize();
string decode(const char* in, string::size_type length);

void
initialize() {
    if (!initializedAlphabet) {
        initializedAlphabet = true;
        // initialize the translation arrays
        for (int i=64; i<256; ++i) {
            inalphabet[i] = 0;
        }
        for (int i=0; i<64; ++i) {
            inalphabet[alphabet[i]] = true;
            decoder[alphabet[i]] = i;
        }
    }
}

Base64InputStream::Base64InputStream(InputStream* i) :p(new Private(this, i)) {
}
Base64InputStream::~Base64InputStream() {
}
Base64InputStream::Private::Private(Base64InputStream* bi, InputStream* i)
        :p(bi), input(i) {
    initialize();
    nleft = 0;
    char_count = 0;
    bits = 0;
    bytestodo = 0;
    pos = pend = 0;
}
bool
Base64InputStream::Private::moreData() {
    if (pos == pend) {
        int32_t nread = input->read(pos, 1, 0);
        if (nread < -1) {
            p->m_status = Error;
            p->m_error = input->error();
            input = 0;
            return false;
        }
        if (nread <= 0) {
            input = 0;
            return false;
        }
        pend = pos + nread;
    }
    return true;
}
int32_t
Base64InputStream::fillBuffer(char* start, int32_t space) {
    return p->fillBuffer(start, space);
}
int32_t
Base64InputStream::Private::fillBuffer(char* start, int32_t space) {
    if (input == 0 && bytestodo == 0) return -1;
    // handle the  bytes that were left over from the last call
    if (bytestodo) {
        switch (bytestodo) {
        case 3:
            *start = bits >> 16;
            break;
        case 2:
            *start = (bits >> 8) & 0xff;
            break;
        case 1:
            *start = bits & 0xff;
            bits = 0;
            char_count = 0;
            break;
        }
        bytestodo--;
        return 1;
    }
    const char* end = start + space;
    char* p = start;
    int32_t nwritten = 0;
    while (moreData()) {
        unsigned char c = *pos++;
        // = signals the end of the encoded block
        if (c == '=') {
            if (char_count == 2) {
                bytestodo = 1;
                bits >>= 10;
            } else if (char_count == 3) {
                bytestodo = 2;
                bits >>= 8;
            }
            input = 0;
            break;
        }
        // we ignore characters that do not fit
        if (!inalphabet[c]) {
            continue;
        }
        bits += decoder[c];
        char_count++;
        if (char_count == 4) {
            if (p >= end) {
                bytestodo = 3;
                break;
            }
            *p++ = bits >> 16;
            if (p >= end) {
                bytestodo = 2;
                nwritten++;
                break;
            }
            *p++ = (bits >> 8) & 0xff;
            if (p >= end) {
                bytestodo = 1;
                nwritten += 2;
                break;
            }
            *p++ = bits & 0xff;
            bits = 0;
            char_count = 0;
            nwritten += 3;
        } else {
            bits <<= 6;
        }
    }
    if (nwritten == 0 && input == 0 && bytestodo == 0) {
//        printf("EOF\n");
        nwritten = -1;
    }
    return nwritten;
}
string
Base64InputStream::decode(const char* in, string::size_type length) {
    initialize();
    string d;
    if (length%4) return d;
    initialize();
    int32_t words = length/4;
    d.reserve(words*3);
    const unsigned char* c = (const unsigned char*)in;
    const unsigned char* e = c + length;
    if (in[length-1] == '=') {
        e -= 4;
    }
    char k, l, b[3];
    for (; c < e; c += 4) {
         if (inalphabet[c[0]]  && inalphabet[c[1]] && inalphabet[c[2]]
             && inalphabet[c[3]]) {
            k = decoder[c[1]];
            l = decoder[c[2]];
            b[0] = (decoder[c[0]] << 2) + (k >> 4);
            b[1] = (k             << 4) + (l >> 2);
            b[2] = (l             << 6) + (decoder[c[3]]);
            d.append(b, 3);
         } else {
             return string();
         }
    }
    if (in[length-2] == '=') {
        if (inalphabet[c[0]]  && inalphabet[c[1]]) {
            b[0] = (decoder[c[0]] << 2)+((decoder[c[1]] >> 4));
            d.append(b, 1);
        } else {
            return string();
        }
    } else if (in[length-1] == '=') {
        if (inalphabet[c[0]]  && inalphabet[c[1]] && inalphabet[c[2]]) {
            k = decoder[c[1]];
            b[0] = (decoder[c[0]] << 2) + (k >> 4);
            b[1] = (k             << 4) + (decoder[c[2]] >> 2);
            d.append(b, 2);
        } else {
            return string();
        }
    }
    return d;
}
<commit_msg>fix a memory leak<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "base64inputstream.h"

#include <cstring>

using namespace std;
using namespace Strigi;

/* code is based on public domain code at
   http://www.tug.org/ftp/vm/base64-decode.c
*/

class Base64InputStream::Private {
public:
    Base64InputStream* const p;
    InputStream* input;
    const char* pos, * pend;
    int32_t bits;
    int32_t nleft;
    char bytestodo;
    char char_count;

    Private(Base64InputStream* p, InputStream* i);
    bool moreData();
    int32_t fillBuffer(char* start, int32_t space);
};

const unsigned char alphabet[]
    = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
bool inalphabet[256];
unsigned char decoder[133];
bool initializedAlphabet = false;
void initialize();
string decode(const char* in, string::size_type length);

void
initialize() {
    if (!initializedAlphabet) {
        initializedAlphabet = true;
        // initialize the translation arrays
        for (int i=64; i<256; ++i) {
            inalphabet[i] = 0;
        }
        for (int i=0; i<64; ++i) {
            inalphabet[alphabet[i]] = true;
            decoder[alphabet[i]] = i;
        }
    }
}

Base64InputStream::Base64InputStream(InputStream* i) :p(new Private(this, i)) {
}
Base64InputStream::~Base64InputStream() {
    delete p;
}
Base64InputStream::Private::Private(Base64InputStream* bi, InputStream* i)
        :p(bi), input(i) {
    initialize();
    nleft = 0;
    char_count = 0;
    bits = 0;
    bytestodo = 0;
    pos = pend = 0;
}
bool
Base64InputStream::Private::moreData() {
    if (pos == pend) {
        int32_t nread = input->read(pos, 1, 0);
        if (nread < -1) {
            p->m_status = Error;
            p->m_error = input->error();
            input = 0;
            return false;
        }
        if (nread <= 0) {
            input = 0;
            return false;
        }
        pend = pos + nread;
    }
    return true;
}
int32_t
Base64InputStream::fillBuffer(char* start, int32_t space) {
    return p->fillBuffer(start, space);
}
int32_t
Base64InputStream::Private::fillBuffer(char* start, int32_t space) {
    if (input == 0 && bytestodo == 0) return -1;
    // handle the  bytes that were left over from the last call
    if (bytestodo) {
        switch (bytestodo) {
        case 3:
            *start = bits >> 16;
            break;
        case 2:
            *start = (bits >> 8) & 0xff;
            break;
        case 1:
            *start = bits & 0xff;
            bits = 0;
            char_count = 0;
            break;
        }
        bytestodo--;
        return 1;
    }
    const char* end = start + space;
    char* p = start;
    int32_t nwritten = 0;
    while (moreData()) {
        unsigned char c = *pos++;
        // = signals the end of the encoded block
        if (c == '=') {
            if (char_count == 2) {
                bytestodo = 1;
                bits >>= 10;
            } else if (char_count == 3) {
                bytestodo = 2;
                bits >>= 8;
            }
            input = 0;
            break;
        }
        // we ignore characters that do not fit
        if (!inalphabet[c]) {
            continue;
        }
        bits += decoder[c];
        char_count++;
        if (char_count == 4) {
            if (p >= end) {
                bytestodo = 3;
                break;
            }
            *p++ = bits >> 16;
            if (p >= end) {
                bytestodo = 2;
                nwritten++;
                break;
            }
            *p++ = (bits >> 8) & 0xff;
            if (p >= end) {
                bytestodo = 1;
                nwritten += 2;
                break;
            }
            *p++ = bits & 0xff;
            bits = 0;
            char_count = 0;
            nwritten += 3;
        } else {
            bits <<= 6;
        }
    }
    if (nwritten == 0 && input == 0 && bytestodo == 0) {
//        printf("EOF\n");
        nwritten = -1;
    }
    return nwritten;
}
string
Base64InputStream::decode(const char* in, string::size_type length) {
    initialize();
    string d;
    if (length%4) return d;
    initialize();
    int32_t words = length/4;
    d.reserve(words*3);
    const unsigned char* c = (const unsigned char*)in;
    const unsigned char* e = c + length;
    if (in[length-1] == '=') {
        e -= 4;
    }
    char k, l, b[3];
    for (; c < e; c += 4) {
         if (inalphabet[c[0]]  && inalphabet[c[1]] && inalphabet[c[2]]
             && inalphabet[c[3]]) {
            k = decoder[c[1]];
            l = decoder[c[2]];
            b[0] = (decoder[c[0]] << 2) + (k >> 4);
            b[1] = (k             << 4) + (l >> 2);
            b[2] = (l             << 6) + (decoder[c[3]]);
            d.append(b, 3);
         } else {
             return string();
         }
    }
    if (in[length-2] == '=') {
        if (inalphabet[c[0]]  && inalphabet[c[1]]) {
            b[0] = (decoder[c[0]] << 2)+((decoder[c[1]] >> 4));
            d.append(b, 1);
        } else {
            return string();
        }
    } else if (in[length-1] == '=') {
        if (inalphabet[c[0]]  && inalphabet[c[1]] && inalphabet[c[2]]) {
            k = decoder[c[1]];
            b[0] = (decoder[c[0]] << 2) + (k >> 4);
            b[1] = (k             << 4) + (decoder[c[2]] >> 2);
            d.append(b, 2);
        } else {
            return string();
        }
    }
    return d;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2015, Roland Bock
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <iostream>
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/sqlpp11.h>
#include <sqlpp11/custom_query.h>

int CustomQuery(int, char* [])
{
  MockDb db = {};
  MockDb::_serializer_context_t printer = {};

  const auto f = test::TabFoo{};
  const auto t = test::TabBar{};

  // A void custom query
  printer.reset();
  auto x = custom_query(sqlpp::verbatim("PRAGMA writeable_schema = "), true);
  std::cerr << serialize(x, printer).str() << std::endl;
  db(x);

  // Syntactically, it is possible to use this void query as a prepared statement, too, not sure, whether this makes
  // sense very often...
  db(db.prepare(x));

  // A prepared custom select
  // The return type of the custom query is determined from the first argument which does have a return type, in this
  // case the select
  auto p = db.prepare(custom_query(select(all_of(t)).from(t), where(t.alpha > sqlpp::parameter(t.alpha))));
  p.params.alpha = 8;
  for (const auto& row : db(p))
  {
    std::cerr << row.alpha << std::endl;
  }

  // Create a custom "insert or ignore"
  db(custom_query(sqlpp::insert(), sqlpp::verbatim(" OR IGNORE"), into(t),
                  insert_set(t.beta = "sample", t.gamma = true)));

  // A custom (select ... into) with adjusted return type
  // The first argument with a return type is the select, but the custom query is really an insert. Thus, we tell it so.
  printer.reset();
  auto c = custom_query(select(all_of(t)).from(t), into(f)).with_result_type_of(insert_into(f));
  std::cerr << serialize(c, printer).str() << std::endl;
  auto i = db(c);
  static_assert(std::is_integral<decltype(i)>::value, "insert yields an integral value");

  return 0;
}
<commit_msg>Add new example to custom_query tests<commit_after>/*
 * Copyright (c) 2013-2015, Roland Bock
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <iostream>
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/sqlpp11.h>
#include <sqlpp11/custom_query.h>

int CustomQuery(int, char* [])
{
  MockDb db = {};
  MockDb::_serializer_context_t printer = {};

  const auto f = test::TabFoo{};
  const auto t = test::TabBar{};

  // A void custom query
  printer.reset();
  auto x = custom_query(sqlpp::verbatim("PRAGMA writeable_schema = "), true);
  std::cerr << serialize(x, printer).str() << std::endl;
  db(x);

  // Syntactically, it is possible to use this void query as a prepared statement, too, not sure, whether this makes
  // sense very often...
  db(db.prepare(x));

  // A prepared custom select
  // The return type of the custom query is determined from the first argument which does have a return type, in this
  // case the select
  auto p = db.prepare(custom_query(select(all_of(t)).from(t), where(t.alpha > sqlpp::parameter(t.alpha))));
  p.params.alpha = 8;
  for (const auto& row : db(p))
  {
    std::cerr << row.alpha << std::endl;
  }

  // Create a custom "insert or ignore"
  db(custom_query(sqlpp::insert(), sqlpp::verbatim(" OR IGNORE"), into(t),
                  insert_set(t.beta = "sample", t.gamma = true)));

  // A custom (select ... into) with adjusted return type
  // The first argument with a return type is the select, but the custom query is really an insert. Thus, we tell it so.
  printer.reset();
  auto c = custom_query(select(all_of(t)).from(t), into(f)).with_result_type_of(insert_into(f));
  std::cerr << serialize(c, printer).str() << std::endl;
  auto i = db(c);
  static_assert(std::is_integral<decltype(i)>::value, "insert yields an integral value");

  for (const auto& row :
       db(custom_query(sqlpp::verbatim("PRAGMA user_version")).with_result_type_of(select(all_of(t)))))
  {
    (void)row.alpha;
  }

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ContentInfo.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: mtg $ $Date: 2001-10-26 21:46:08 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _CONTENT_INFO_HXX_
#define _CONTENT_INFO_HXX_

#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEl_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _ZIP_PACKAGE_FOLDER_HXX
#include <ZipPackageFolder.hxx>
#endif
#ifndef _ZIP_PACKAGE_STREAM_HXX
#include <ZipPackageStream.hxx>
#endif
#include <hash_map>

struct ContentInfo
{
    com::sun::star::uno::Reference < com::sun::star::lang::XUnoTunnel > xTunnel;
    bool bFolder;
    union
    {
        ZipPackageFolder *pFolder;
        ZipPackageStream *pStream;
    };
    ContentInfo ( ZipPackageStream * pNewStream )
    : bFolder ( false )
    , pStream ( pNewStream )
    , xTunnel ( pNewStream )
    {
    }
    ContentInfo ( ZipPackageFolder * pNewFolder )
    : bFolder ( true )
    , pFolder ( pNewFolder )
    , xTunnel ( pNewFolder )
    {
    }
    ~ContentInfo ()
    {
        if (bFolder)
            pFolder->releaseUpwardRef();
    }
};
#endif
<commit_msg>#93877# derive ContentInfo from OWeakObject so we can use it in an ORef<commit_after>/*************************************************************************
 *
 *  $RCSfile: ContentInfo.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: mtg $ $Date: 2001-10-30 13:54:47 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _CONTENT_INFO_HXX_
#define _CONTENT_INFO_HXX_

#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEl_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _ZIP_PACKAGE_FOLDER_HXX
#include <ZipPackageFolder.hxx>
#endif
#ifndef _ZIP_PACKAGE_STREAM_HXX
#include <ZipPackageStream.hxx>
#endif
#include <hash_map>

class ContentInfo : public cppu::OWeakObject
{
public:
    com::sun::star::uno::Reference < com::sun::star::lang::XUnoTunnel > xTunnel;
    bool bFolder;
    union
    {
        ZipPackageFolder *pFolder;
        ZipPackageStream *pStream;
    };
    ContentInfo ( ZipPackageStream * pNewStream )
    : bFolder ( false )
    , pStream ( pNewStream )
    , xTunnel ( pNewStream )
    {
    }
    ContentInfo ( ZipPackageFolder * pNewFolder )
    : bFolder ( true )
    , pFolder ( pNewFolder )
    , xTunnel ( pNewFolder )
    {
    }
    virtual ~ContentInfo ()
    {
        if ( bFolder )
            pFolder->releaseUpwardRef();
    }
};
#endif
<|endoftext|>


<commit_before>#include <cstdlib>
#include <cstring>
#include "videosourcefactory.h"

using namespace gg;

void show_error(int argc, char *argv[])
{
    printf("Please check CLI args of:\n");
    for (int i = 0; i < argc - 1; i++)
        printf("%s ", argv[i]);
    printf("%s\n", argv[argc - 1]);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    if (argc < 3)
        show_error(argc, argv);

    Device device;
    if (std::strcmp(argv[1], "DVI2PCIeDuo_SDI") == 0)
        device = Device::DVI2PCIeDuo_SDI;
    else if (std::strcmp(argv[1], "DVI2PCIeDuo_DVI") == 0)
        device = Device::DVI2PCIeDuo_DVI;
    else if (std::strcmp(argv[1], "DeckLinkSDI4K") == 0)
        device = Device::DeckLinkSDI4K;
    else if (std::strcmp(argv[1], "DeckLink4KExtreme12G") == 0)
        device = Device::DeckLink4KExtreme12G;
    else
        show_error(argc, argv);

    ColourSpace colour;
    if (std::strcmp(argv[2], "BGRA") == 0)
        colour = ColourSpace::BGRA;
    else if (std::strcmp(argv[2], "I420") == 0)
        colour = ColourSpace::I420;
    else if (std::strcmp(argv[2], "UYVY") == 0)
        colour = ColourSpace::UYVY;
    else
        show_error(argc, argv);

    VideoSourceFactory &factory = VideoSourceFactory::get_instance();
    IVideoSource *source = factory.get_device(device, colour);

    /* Upon exiting, the factory should free all
     * allocated memory. So there should be no
     * leaks.
     */
    return EXIT_SUCCESS;
}
<commit_msg>Issue #14: leak checker app now catches DeviceOffline for console-friendly error message display<commit_after>#include <cstdlib>
#include <cstring>
#include "videosourcefactory.h"

using namespace gg;

void show_error(int argc, char *argv[])
{
    printf("Please check CLI args of:\n");
    for (int i = 0; i < argc - 1; i++)
        printf("%s ", argv[i]);
    printf("%s\n", argv[argc - 1]);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    if (argc < 3)
        show_error(argc, argv);

    Device device;
    if (std::strcmp(argv[1], "DVI2PCIeDuo_SDI") == 0)
        device = Device::DVI2PCIeDuo_SDI;
    else if (std::strcmp(argv[1], "DVI2PCIeDuo_DVI") == 0)
        device = Device::DVI2PCIeDuo_DVI;
    else if (std::strcmp(argv[1], "DeckLinkSDI4K") == 0)
        device = Device::DeckLinkSDI4K;
    else if (std::strcmp(argv[1], "DeckLink4KExtreme12G") == 0)
        device = Device::DeckLink4KExtreme12G;
    else
        show_error(argc, argv);

    ColourSpace colour;
    if (std::strcmp(argv[2], "BGRA") == 0)
        colour = ColourSpace::BGRA;
    else if (std::strcmp(argv[2], "I420") == 0)
        colour = ColourSpace::I420;
    else if (std::strcmp(argv[2], "UYVY") == 0)
        colour = ColourSpace::UYVY;
    else
        show_error(argc, argv);

    VideoSourceFactory &factory = VideoSourceFactory::get_instance();
    try
    {
        IVideoSource *source = factory.get_device(device, colour);
    }
    catch (gg::DeviceOffline &device_offline)
    {
        printf("Device offline\n");
        return EXIT_FAILURE;
    }
    printf("OK\n");

    /* Upon exiting, the factory should free all
     * allocated memory. So there should be no
     * leaks.
     */
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#pragma once

#include <mutex>

class local_datagram_client final {
public:
  local_datagram_client(const char* _Nonnull path) : endpoint_(path),
                                                     io_service_(),
                                                     work_(io_service_),
                                                     socket_(io_service_) {
    socket_.open();
    thread_ = std::thread([this] { (this->io_service_).run(); });
  }

  ~local_datagram_client(void) {
    io_service_.stop();
    thread_.join();
  }

  void send_to(const uint8_t* _Nonnull buffer, size_t buffer_length) {
    std::lock_guard<std::mutex> lock(mutex_);

    auto item_ptr = std::make_shared<item>(buffer, buffer_length);
    queue_.push_back(item_ptr);
    io_service_.post(boost::bind(&local_datagram_client::do_send, this, boost::ref(*item_ptr)));
  }

private:
  class item final {
  public:
    item(const uint8_t* _Nonnull buffer, size_t buffer_length) : id_(get_next_id()) {
      buffer_.resize(buffer_length);
      memcpy(&(buffer_[0]), buffer, buffer_length);
    }

    static uint64_t get_next_id(void) {
      static uint64_t id;
      return ++id;
    }

    uint64_t get_id(void) const { return id_; }
    const std::vector<uint8_t> get_buffer(void) const { return buffer_; }

  private:
    uint64_t id_;
    std::vector<uint8_t> buffer_;
  };

  void do_send(const item& item) {
    socket_.async_send_to(boost::asio::buffer(item.get_buffer()), endpoint_,
                          boost::bind(&local_datagram_client::handle_send, this, item.get_id()));
  }

  void handle_send(uint64_t item_id) {
    std::lock_guard<std::mutex> lock(mutex_);

    for (const auto& i : queue_) {
      if (i->get_id() == item_id) {
        queue_.remove(i);
        return;
      }
    }
  }

  boost::asio::local::datagram_protocol::endpoint endpoint_;
  boost::asio::io_service io_service_;
  boost::asio::io_service::work work_;
  boost::asio::local::datagram_protocol::socket socket_;
  std::thread thread_;
  std::mutex mutex_;
  std::list<std::shared_ptr<item>> queue_;
};
<commit_msg>remove queue_<commit_after>#pragma once

class local_datagram_client final {
public:
  local_datagram_client(const char* _Nonnull path) : endpoint_(path),
                                                     io_service_(),
                                                     work_(io_service_),
                                                     socket_(io_service_) {
    socket_.open();
    thread_ = std::thread([this] { (this->io_service_).run(); });
  }

  ~local_datagram_client(void) {
    io_service_.stop();
    thread_.join();
  }

  void send_to(const uint8_t* _Nonnull buffer, size_t buffer_length) {
    auto ptr = std::make_shared<std::vector<uint8_t>>();
    ptr->resize(buffer_length);
    memcpy(&((*ptr)[0]), buffer, buffer_length);
    io_service_.post(boost::bind(&local_datagram_client::do_send, this, ptr));
  }

private:
  void do_send(const std::shared_ptr<std::vector<uint8_t>>& ptr) {
    socket_.async_send_to(boost::asio::buffer(*ptr), endpoint_,
                          boost::bind(&local_datagram_client::handle_send, this, ptr));
  }

  void handle_send(const std::shared_ptr<std::vector<uint8_t>>& ptr) {
    // shared_ptr will be released.
  }

  boost::asio::local::datagram_protocol::endpoint endpoint_;
  boost::asio::io_service io_service_;
  boost::asio::io_service::work work_;
  boost::asio::local::datagram_protocol::socket socket_;
  std::thread thread_;
};
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/common/plat/p10/prdfP10Eq.C $               */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2020,2021                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <prdfPluginDef.H>
#include <iipServiceDataCollector.h>
#include <prdfExtensibleChip.H>
#include <prdfPluginMap.H>

using namespace TARGETING;

namespace PRDF
{

using namespace PlatServices;

namespace p10_eq
{

/**
 * @brief  Plugin function for handling the core UCS summary bit
 * @param  i_chip    EQ chip.
 * @param  io_sc     The step code data struct.
 * @return Return code from analysis of the UCS. SUCCESS if no UCS found.
 */
int32_t analyzeUcs( ExtensibleChip * i_chip, STEP_CODE_DATA_STRUCT & io_sc )
{
    // Check the EQ_CHIPLET_UCS_FIR for which core has a UCS
    auto fir = i_chip->getRegister("EQ_CHIPLET_UCS_FIR");
    auto msk = i_chip->getRegister("EQ_CHIPLET_UCS_FIR_MASK");

    if ( SUCCESS == (fir->Read() | msk->Read()) )
    {
        // NOTE: If analysis fails on one core, check the other cores.

        // Bit 5 = Core 0
        if ( fir->IsBitSet(5) && !msk->IsBitSet(5) )
        {
            ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, 0 );
            if (SUCCESS == core->Analyze(io_sc, UNIT_CS))
                return SUCCESS;
        }

        // Bit 6 = Core 1
        if ( fir->IsBitSet(6) && !msk->IsBitSet(6) )
        {
            ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, 1 );
            if (SUCCESS == core->Analyze(io_sc, UNIT_CS))
                return SUCCESS;
        }

        // Bit 7 = Core 2
        if ( fir->IsBitSet(7) && !msk->IsBitSet(7) )
        {
            ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, 2 );
            if (SUCCESS == core->Analyze(io_sc, UNIT_CS))
                return SUCCESS;
        }

        // Bit 8 = Core 3
        if ( fir->IsBitSet(8) && !msk->IsBitSet(8) )
        {
            ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, 3 );
            if (SUCCESS == core->Analyze(io_sc, UNIT_CS))
                return SUCCESS;
        }
    }

    return PRD_SCAN_COMM_REGISTER_ZERO; // default if nothing found
}
PRDF_PLUGIN_DEFINE( p10_eq, analyzeUcs );

/**
 * @brief  Plugin function for recoverable analysis to the core and then to
 *         mask the EQ_CORE_FIR off at the EQ chiplet level if at threshold.
 * @param  i_chip    An EQ chip.
 * @param  io_sc     The step code data struct.
 * @param  i_corePos The position of the analyzed core.
 * @return SUCCESS if analysis to core completes, else the failed return code
 *         from analysis.
 */
int32_t __analyzeCoreFir( ExtensibleChip * i_chip,
                          STEP_CODE_DATA_STRUCT & io_sc, uint8_t i_corePos )
{
    #define PRDF_FUNC "[p10_eq::__analyzeCoreFir] "

    int32_t o_rc = SUCCESS;

    // First, analyze to the core. If analysis is not successful, just return
    // the failed return code.
    ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, i_corePos );
    o_rc = core->Analyze( io_sc, RECOVERABLE );
    if ( SUCCESS != o_rc )
    {
        PRDF_TRAC(PRDF_FUNC "Analysis failed to core 0x%08x", core->getHuid());
        return o_rc;
    }

    // Note that we cannot set the mask of recoverable bits that have reached
    // threshold in the EQ_CORE_FIR. Instead, we will mask the core off at the
    // EQ_CHIPLET_RE_FIR level here.

    #ifdef __HOSTBOOT_MODULE

    // Mask and clear EQ_CORE_FIR recoverable attentions.
    if (RECOVERABLE == io_sc.service_data->getPrimaryAttnType())
    {
        if (io_sc.service_data->IsAtThreshold())
        {
            // We can't mask recoverable errors in the CORE_FIR like we do on
            // all of the other FIRs because it will cause core recovery to
            // hang. Therefore, we will we will mask recoverable attentions for
            // the entire FIR (at threshold).
            auto chipletMask = i_chip->getRegister("EQ_CHIPLET_RE_FIR_MASK");

            if ( SUCCESS == chipletMask->Read() )
            {
                // Bits 5:8 are the bits for analysis to the EQ_CORE_FIR
                chipletMask->SetBit( 5 + i_corePos );

                if ( SUCCESS != chipletMask->Write() )
                {
                    PRDF_ERR(PRDF_FUNC "Failed to write EQ_CHIPLET_RE_FIR_MASK "
                             "on 0x%08x", i_chip->getHuid());
                }
            }
            else
            {
                PRDF_ERR(PRDF_FUNC "Failed to read EQ_CHIPLET_RE_FIR_MASK on "
                         "0x%08x", i_chip->getHuid());
            }
        }

        // If there is a recoverable attention on a core in fused core mode,
        // EQ_CORE_FIR_WOF[56] will be set by hardware on the other core in the
        // core pair. If this bit is left on, PHYP will be unable to put the
        // core to sleep, which is a small hit to power performance. Therefore,
        // we need to ensure this bit is clear. Note that it is possible the
        // rule code will clear it. So check if it is set before writing again.
        auto neighbor = getNeighborCore(core);
        if (nullptr != neighbor)
        {
            auto wof = neighbor->getRegister("EQ_CORE_FIR_WOF");
            if (SUCCESS == wof->Read() && wof->IsBitSet(56))
            {
                wof->ClearBit(56);
                wof->Write();
            }
        }
    }

    #endif // __HOSTBOOT_MODULE

    return o_rc;

    #undef PRDF_FUNC
}

#define PLUGIN_ANALYZE_CORE_FIR( POS ) \
int32_t analyzeCoreFir_##POS( ExtensibleChip * i_chip, \
                              STEP_CODE_DATA_STRUCT & io_sc ) \
{ \
    return __analyzeCoreFir( i_chip, io_sc, POS ); \
} \
PRDF_PLUGIN_DEFINE( p10_eq, analyzeCoreFir_##POS );

PLUGIN_ANALYZE_CORE_FIR(0);
PLUGIN_ANALYZE_CORE_FIR(1);
PLUGIN_ANALYZE_CORE_FIR(2);
PLUGIN_ANALYZE_CORE_FIR(3);

} // namespace p10_eq

} // namespace PRDF
<commit_msg>PRD: mask recov attn on both fused cores at threshold<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/usr/diag/prdf/common/plat/p10/prdfP10Eq.C $               */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2020,2021                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <prdfPluginDef.H>
#include <iipServiceDataCollector.h>
#include <prdfExtensibleChip.H>
#include <prdfPluginMap.H>

using namespace TARGETING;

namespace PRDF
{

using namespace PlatServices;

namespace p10_eq
{

/**
 * @brief  Plugin function for handling the core UCS summary bit
 * @param  i_chip    EQ chip.
 * @param  io_sc     The step code data struct.
 * @return Return code from analysis of the UCS. SUCCESS if no UCS found.
 */
int32_t analyzeUcs( ExtensibleChip * i_chip, STEP_CODE_DATA_STRUCT & io_sc )
{
    // Check the EQ_CHIPLET_UCS_FIR for which core has a UCS
    auto fir = i_chip->getRegister("EQ_CHIPLET_UCS_FIR");
    auto msk = i_chip->getRegister("EQ_CHIPLET_UCS_FIR_MASK");

    if ( SUCCESS == (fir->Read() | msk->Read()) )
    {
        // NOTE: If analysis fails on one core, check the other cores.

        // Bit 5 = Core 0
        if ( fir->IsBitSet(5) && !msk->IsBitSet(5) )
        {
            ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, 0 );
            if (SUCCESS == core->Analyze(io_sc, UNIT_CS))
                return SUCCESS;
        }

        // Bit 6 = Core 1
        if ( fir->IsBitSet(6) && !msk->IsBitSet(6) )
        {
            ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, 1 );
            if (SUCCESS == core->Analyze(io_sc, UNIT_CS))
                return SUCCESS;
        }

        // Bit 7 = Core 2
        if ( fir->IsBitSet(7) && !msk->IsBitSet(7) )
        {
            ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, 2 );
            if (SUCCESS == core->Analyze(io_sc, UNIT_CS))
                return SUCCESS;
        }

        // Bit 8 = Core 3
        if ( fir->IsBitSet(8) && !msk->IsBitSet(8) )
        {
            ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, 3 );
            if (SUCCESS == core->Analyze(io_sc, UNIT_CS))
                return SUCCESS;
        }
    }

    return PRD_SCAN_COMM_REGISTER_ZERO; // default if nothing found
}
PRDF_PLUGIN_DEFINE( p10_eq, analyzeUcs );

/**
 * @brief  Plugin function for recoverable analysis to the core and then to
 *         mask the EQ_CORE_FIR off at the EQ chiplet level if at threshold.
 * @param  i_chip    An EQ chip.
 * @param  io_sc     The step code data struct.
 * @param  i_corePos The position of the analyzed core.
 * @return SUCCESS if analysis to core completes, else the failed return code
 *         from analysis.
 */
int32_t __analyzeCoreFir( ExtensibleChip * i_chip,
                          STEP_CODE_DATA_STRUCT & io_sc, uint8_t i_corePos )
{
    #define PRDF_FUNC "[p10_eq::__analyzeCoreFir] "

    int32_t o_rc = SUCCESS;

    // First, analyze to the core. If analysis is not successful, just return
    // the failed return code.
    ExtensibleChip * core = getConnectedChild( i_chip, TYPE_CORE, i_corePos );
    o_rc = core->Analyze( io_sc, RECOVERABLE );
    if ( SUCCESS != o_rc )
    {
        PRDF_TRAC(PRDF_FUNC "Analysis failed to core 0x%08x", core->getHuid());
        return o_rc;
    }

    // Note that we cannot set the mask of recoverable bits that have reached
    // threshold in the EQ_CORE_FIR. Instead, we will mask the core off at the
    // EQ_CHIPLET_RE_FIR level here.

    #ifdef __HOSTBOOT_MODULE

    // Mask and clear EQ_CORE_FIR recoverable attentions.
    if (RECOVERABLE == io_sc.service_data->getPrimaryAttnType())
    {
        if (io_sc.service_data->IsAtThreshold())
        {
            // We can't mask recoverable errors in the CORE_FIR like we do on
            // all of the other FIRs because it will cause core recovery to
            // hang. Therefore, we will mask recoverable attentions for the
            // entire FIR (at threshold).
            auto chipletMask = i_chip->getRegister("EQ_CHIPLET_RE_FIR_MASK");

            if ( SUCCESS == chipletMask->Read() )
            {
                // EQ_CHIPLET_RE_FIR_MASK[5:8] is for the four attached cores.
                // In fused core mode, any other FIR bits that fire in a masked
                // core will trigger EQ_CORE_FIR_WOF[56] in the neighbor core.
                // To prevent the unexpected attentions, we will need to mask
                // off both cores in the fused core pair.
                for (const auto& c : {core, getNeighborCore(core)})
                {
                    if (nullptr == c) continue; // in case neighbor core is null

                    chipletMask->SetBit(5 + (c->getPos() % MAX_EC_PER_EQ));
                }

                if ( SUCCESS != chipletMask->Write() )
                {
                    PRDF_ERR(PRDF_FUNC "Failed to write EQ_CHIPLET_RE_FIR_MASK "
                             "on 0x%08x", i_chip->getHuid());
                }
            }
            else
            {
                PRDF_ERR(PRDF_FUNC "Failed to read EQ_CHIPLET_RE_FIR_MASK on "
                         "0x%08x", i_chip->getHuid());
            }
        }

        // If there is a recoverable attention on a core in fused core mode,
        // EQ_CORE_FIR_WOF[56] will be set by hardware on the other core in the
        // core pair. If this bit is left on, PHYP will be unable to put the
        // core to sleep, which is a small hit to power performance. Therefore,
        // we need to ensure this bit is clear. Note that it is possible the
        // rule code will clear it. So check if it is set before writing again.
        auto neighbor = getNeighborCore(core);
        if (nullptr != neighbor)
        {
            auto wof = neighbor->getRegister("EQ_CORE_FIR_WOF");
            if (SUCCESS == wof->Read() && wof->IsBitSet(56))
            {
                wof->ClearBit(56);
                wof->Write();
            }
        }
    }

    #endif // __HOSTBOOT_MODULE

    return o_rc;

    #undef PRDF_FUNC
}

#define PLUGIN_ANALYZE_CORE_FIR( POS ) \
int32_t analyzeCoreFir_##POS( ExtensibleChip * i_chip, \
                              STEP_CODE_DATA_STRUCT & io_sc ) \
{ \
    return __analyzeCoreFir( i_chip, io_sc, POS ); \
} \
PRDF_PLUGIN_DEFINE( p10_eq, analyzeCoreFir_##POS );

PLUGIN_ANALYZE_CORE_FIR(0);
PLUGIN_ANALYZE_CORE_FIR(1);
PLUGIN_ANALYZE_CORE_FIR(2);
PLUGIN_ANALYZE_CORE_FIR(3);

} // namespace p10_eq

} // namespace PRDF
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "core/paint/SVGShapePainter.h"

#include "core/layout/svg/SVGLayoutContext.h"
#include "core/layout/svg/SVGLayoutSupport.h"
#include "core/layout/svg/SVGMarkerData.h"
#include "core/layout/svg/SVGResources.h"
#include "core/layout/svg/SVGResourcesCache.h"
#include "core/paint/GraphicsContextAnnotator.h"
#include "core/paint/ObjectPainter.h"
#include "core/paint/RenderDrawingRecorder.h"
#include "core/paint/SVGContainerPainter.h"
#include "core/paint/TransformRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/svg/RenderSVGPath.h"
#include "core/rendering/svg/RenderSVGResourceMarker.h"
#include "core/rendering/svg/RenderSVGShape.h"
#include "platform/graphics/paint/DisplayItemList.h"
#include "third_party/skia/include/core/SkPicture.h"

namespace blink {

static bool setupNonScalingStrokeContext(AffineTransform& strokeTransform, GraphicsContextStateSaver& stateSaver)
{
    if (!strokeTransform.isInvertible())
        return false;

    stateSaver.save();
    stateSaver.context()->concatCTM(strokeTransform.inverse());
    return true;
}

static void useStrokeStyleToFill(GraphicsContext* context)
{
    if (Gradient* gradient = context->strokeGradient())
        context->setFillGradient(gradient);
    else if (Pattern* pattern = context->strokePattern())
        context->setFillPattern(pattern);
    else
        context->setFillColor(context->strokeColor());
}

void SVGShapePainter::paint(const PaintInfo& paintInfo)
{
    ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderSVGShape);
    if (paintInfo.phase != PaintPhaseForeground
        || m_renderSVGShape.style()->visibility() == HIDDEN
        || m_renderSVGShape.isShapeEmpty())
        return;

    PaintInfo paintInfoBeforeFiltering(paintInfo);
    FloatRect boundingBox = m_renderSVGShape.paintInvalidationRectInLocalCoordinates();

    TransformRecorder transformRecorder(*paintInfoBeforeFiltering.context, m_renderSVGShape.displayItemClient(), m_renderSVGShape.localTransform());
    {
        SVGLayoutContext renderingContext(m_renderSVGShape, paintInfoBeforeFiltering);
        if (renderingContext.applyClipMaskAndFilterIfNecessary()) {
            RenderDrawingRecorder recorder(renderingContext.paintInfo().context, m_renderSVGShape, renderingContext.paintInfo().phase, boundingBox);
            if (!recorder.canUseCachedDrawing()) {
                const SVGRenderStyle& svgStyle = m_renderSVGShape.style()->svgStyle();
                if (svgStyle.shapeRendering() == SR_CRISPEDGES)
                    renderingContext.paintInfo().context->setShouldAntialias(false);

                for (int i = 0; i < 3; i++) {
                    switch (svgStyle.paintOrderType(i)) {
                    case PT_FILL: {
                        GraphicsContextStateSaver stateSaver(*renderingContext.paintInfo().context, false);
                        if (!SVGLayoutSupport::updateGraphicsContext(renderingContext.paintInfo(), stateSaver, m_renderSVGShape.styleRef(), m_renderSVGShape, ApplyToFillMode))
                            break;
                        fillShape(renderingContext.paintInfo().context);
                        break;
                    }
                    case PT_STROKE:
                        if (svgStyle.hasVisibleStroke()) {
                            GraphicsContextStateSaver stateSaver(*renderingContext.paintInfo().context, false);
                            AffineTransform nonScalingTransform;
                            const AffineTransform* additionalPaintServerTransform = 0;

                            if (m_renderSVGShape.hasNonScalingStroke()) {
                                nonScalingTransform = m_renderSVGShape.nonScalingStrokeTransform();
                                if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
                                    return;

                                // Non-scaling stroke needs to reset the transform back to the host transform.
                                additionalPaintServerTransform = &nonScalingTransform;
                            }

                            if (!SVGLayoutSupport::updateGraphicsContext(renderingContext.paintInfo(), stateSaver, m_renderSVGShape.styleRef(), m_renderSVGShape, ApplyToStrokeMode, additionalPaintServerTransform))
                                break;
                            strokeShape(renderingContext.paintInfo().context);
                        }
                        break;
                    case PT_MARKERS:
                        paintMarkers(renderingContext.paintInfo());
                        break;
                    default:
                        ASSERT_NOT_REACHED();
                        break;
                    }
                }
            }
        }
    }

    if (m_renderSVGShape.style()->outlineWidth())
        ObjectPainter(m_renderSVGShape).paintOutline(paintInfoBeforeFiltering, LayoutRect(boundingBox));
}

void SVGShapePainter::fillShape(GraphicsContext* context)
{
    switch (m_renderSVGShape.geometryCodePath()) {
    case RectGeometryFastPath:
        context->fillRect(m_renderSVGShape.objectBoundingBox());
        break;
    case EllipseGeometryFastPath:
        context->fillEllipse(m_renderSVGShape.objectBoundingBox());
        break;
    default:
        context->fillPath(m_renderSVGShape.path());
    }
}

void SVGShapePainter::strokeShape(GraphicsContext* context)
{
    if (!m_renderSVGShape.style()->svgStyle().hasVisibleStroke())
        return;

    switch (m_renderSVGShape.geometryCodePath()) {
    case RectGeometryFastPath:
        context->strokeRect(m_renderSVGShape.objectBoundingBox(), m_renderSVGShape.strokeWidth());
        break;
    case EllipseGeometryFastPath:
        context->strokeEllipse(m_renderSVGShape.objectBoundingBox());
        break;
    default:
        ASSERT(m_renderSVGShape.hasPath());
        Path* usePath = &m_renderSVGShape.path();
        if (m_renderSVGShape.hasNonScalingStroke())
            usePath = m_renderSVGShape.nonScalingStrokePath(usePath, m_renderSVGShape.nonScalingStrokeTransform());
        context->strokePath(*usePath);
        strokeZeroLengthLineCaps(context);
    }
}

void SVGShapePainter::paintMarkers(const PaintInfo& paintInfo)
{
    const Vector<MarkerPosition>* markerPositions = m_renderSVGShape.markerPositions();
    if (!markerPositions || markerPositions->isEmpty())
        return;

    SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(&m_renderSVGShape);
    if (!resources)
        return;

    RenderSVGResourceMarker* markerStart = resources->markerStart();
    RenderSVGResourceMarker* markerMid = resources->markerMid();
    RenderSVGResourceMarker* markerEnd = resources->markerEnd();
    if (!markerStart && !markerMid && !markerEnd)
        return;

    float strokeWidth = m_renderSVGShape.strokeWidth();
    unsigned size = markerPositions->size();
    for (unsigned i = 0; i < size; ++i) {
        if (RenderSVGResourceMarker* marker = SVGMarkerData::markerForType((*markerPositions)[i].type, markerStart, markerMid, markerEnd))
            paintMarker(paintInfo, *marker, (*markerPositions)[i], strokeWidth);
    }
}

void SVGShapePainter::paintMarker(const PaintInfo& paintInfo, RenderSVGResourceMarker& marker, const MarkerPosition& position, float strokeWidth)
{
    // An empty viewBox disables rendering.
    SVGMarkerElement* markerElement = toSVGMarkerElement(marker.element());
    ASSERT(markerElement);
    if (markerElement->hasAttribute(SVGNames::viewBoxAttr) && markerElement->viewBox()->currentValue()->isValid() && markerElement->viewBox()->currentValue()->value().isEmpty())
        return;

    OwnPtr<DisplayItemList> displayItemList;
    if (RuntimeEnabledFeatures::slimmingPaintEnabled())
        displayItemList = DisplayItemList::create();
    GraphicsContext recordingContext(nullptr, displayItemList.get());
    recordingContext.beginRecording(m_renderSVGShape.paintInvalidationRectInLocalCoordinates());

    PaintInfo markerPaintInfo(paintInfo);
    markerPaintInfo.context = &recordingContext;
    {
        TransformRecorder transformRecorder(*markerPaintInfo.context, marker.displayItemClient(), marker.markerTransformation(position.origin, position.angle, strokeWidth));
        OwnPtr<FloatClipRecorder> clipRecorder;
        if (SVGLayoutSupport::isOverflowHidden(&marker))
            clipRecorder = adoptPtr(new FloatClipRecorder(recordingContext, marker.displayItemClient(), markerPaintInfo.phase, marker.viewport()));

        SVGContainerPainter(marker).paint(markerPaintInfo);
    }

    if (displayItemList)
        displayItemList->replay(&recordingContext);
    RefPtr<const SkPicture> recording = recordingContext.endRecording();
    paintInfo.context->drawPicture(recording.get());
}

void SVGShapePainter::strokeZeroLengthLineCaps(GraphicsContext* context)
{
    const Vector<FloatPoint>* zeroLengthLineCaps = m_renderSVGShape.zeroLengthLineCaps();
    if (!zeroLengthLineCaps || zeroLengthLineCaps->isEmpty())
        return;

    Path* usePath;
    AffineTransform nonScalingTransform;

    if (m_renderSVGShape.hasNonScalingStroke())
        nonScalingTransform = m_renderSVGShape.nonScalingStrokeTransform();

    GraphicsContextStateSaver stateSaver(*context, true);
    useStrokeStyleToFill(context);
    for (size_t i = 0; i < zeroLengthLineCaps->size(); ++i) {
        usePath = zeroLengthLinecapPath((*zeroLengthLineCaps)[i]);
        if (m_renderSVGShape.hasNonScalingStroke())
            usePath = m_renderSVGShape.nonScalingStrokePath(usePath, nonScalingTransform);
        context->fillPath(*usePath);
    }
}

Path* SVGShapePainter::zeroLengthLinecapPath(const FloatPoint& linecapPosition) const
{
    DEFINE_STATIC_LOCAL(Path, tempPath, ());

    tempPath.clear();
    if (m_renderSVGShape.style()->svgStyle().capStyle() == SquareCap)
        tempPath.addRect(RenderSVGPath::zeroLengthSubpathRect(linecapPosition, m_renderSVGShape.strokeWidth()));
    else
        tempPath.addEllipse(RenderSVGPath::zeroLengthSubpathRect(linecapPosition, m_renderSVGShape.strokeWidth()));

    return &tempPath;
}

} // namespace blink
<commit_msg>Unique display item ids: SVGShape outline<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "config.h"
#include "core/paint/SVGShapePainter.h"

#include "core/layout/svg/SVGLayoutContext.h"
#include "core/layout/svg/SVGLayoutSupport.h"
#include "core/layout/svg/SVGMarkerData.h"
#include "core/layout/svg/SVGResources.h"
#include "core/layout/svg/SVGResourcesCache.h"
#include "core/paint/GraphicsContextAnnotator.h"
#include "core/paint/ObjectPainter.h"
#include "core/paint/RenderDrawingRecorder.h"
#include "core/paint/SVGContainerPainter.h"
#include "core/paint/TransformRecorder.h"
#include "core/rendering/PaintInfo.h"
#include "core/rendering/svg/RenderSVGPath.h"
#include "core/rendering/svg/RenderSVGResourceMarker.h"
#include "core/rendering/svg/RenderSVGShape.h"
#include "platform/graphics/paint/DisplayItemList.h"
#include "third_party/skia/include/core/SkPicture.h"

namespace blink {

static bool setupNonScalingStrokeContext(AffineTransform& strokeTransform, GraphicsContextStateSaver& stateSaver)
{
    if (!strokeTransform.isInvertible())
        return false;

    stateSaver.save();
    stateSaver.context()->concatCTM(strokeTransform.inverse());
    return true;
}

static void useStrokeStyleToFill(GraphicsContext* context)
{
    if (Gradient* gradient = context->strokeGradient())
        context->setFillGradient(gradient);
    else if (Pattern* pattern = context->strokePattern())
        context->setFillPattern(pattern);
    else
        context->setFillColor(context->strokeColor());
}

void SVGShapePainter::paint(const PaintInfo& paintInfo)
{
    ANNOTATE_GRAPHICS_CONTEXT(paintInfo, &m_renderSVGShape);
    if (paintInfo.phase != PaintPhaseForeground
        || m_renderSVGShape.style()->visibility() == HIDDEN
        || m_renderSVGShape.isShapeEmpty())
        return;

    PaintInfo paintInfoBeforeFiltering(paintInfo);
    FloatRect boundingBox = m_renderSVGShape.paintInvalidationRectInLocalCoordinates();

    TransformRecorder transformRecorder(*paintInfoBeforeFiltering.context, m_renderSVGShape.displayItemClient(), m_renderSVGShape.localTransform());
    {
        SVGLayoutContext renderingContext(m_renderSVGShape, paintInfoBeforeFiltering);
        if (renderingContext.applyClipMaskAndFilterIfNecessary()) {
            RenderDrawingRecorder recorder(renderingContext.paintInfo().context, m_renderSVGShape, renderingContext.paintInfo().phase, boundingBox);
            if (!recorder.canUseCachedDrawing()) {
                const SVGRenderStyle& svgStyle = m_renderSVGShape.style()->svgStyle();
                if (svgStyle.shapeRendering() == SR_CRISPEDGES)
                    renderingContext.paintInfo().context->setShouldAntialias(false);

                for (int i = 0; i < 3; i++) {
                    switch (svgStyle.paintOrderType(i)) {
                    case PT_FILL: {
                        GraphicsContextStateSaver stateSaver(*renderingContext.paintInfo().context, false);
                        if (!SVGLayoutSupport::updateGraphicsContext(renderingContext.paintInfo(), stateSaver, m_renderSVGShape.styleRef(), m_renderSVGShape, ApplyToFillMode))
                            break;
                        fillShape(renderingContext.paintInfo().context);
                        break;
                    }
                    case PT_STROKE:
                        if (svgStyle.hasVisibleStroke()) {
                            GraphicsContextStateSaver stateSaver(*renderingContext.paintInfo().context, false);
                            AffineTransform nonScalingTransform;
                            const AffineTransform* additionalPaintServerTransform = 0;

                            if (m_renderSVGShape.hasNonScalingStroke()) {
                                nonScalingTransform = m_renderSVGShape.nonScalingStrokeTransform();
                                if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
                                    return;

                                // Non-scaling stroke needs to reset the transform back to the host transform.
                                additionalPaintServerTransform = &nonScalingTransform;
                            }

                            if (!SVGLayoutSupport::updateGraphicsContext(renderingContext.paintInfo(), stateSaver, m_renderSVGShape.styleRef(), m_renderSVGShape, ApplyToStrokeMode, additionalPaintServerTransform))
                                break;
                            strokeShape(renderingContext.paintInfo().context);
                        }
                        break;
                    case PT_MARKERS:
                        paintMarkers(renderingContext.paintInfo());
                        break;
                    default:
                        ASSERT_NOT_REACHED();
                        break;
                    }
                }
            }
        }
    }

    if (m_renderSVGShape.style()->outlineWidth()) {
        PaintInfo outlinePaintInfo(paintInfoBeforeFiltering);
        outlinePaintInfo.phase = PaintPhaseSelfOutline;
        ObjectPainter(m_renderSVGShape).paintOutline(outlinePaintInfo, LayoutRect(boundingBox));
    }
}

void SVGShapePainter::fillShape(GraphicsContext* context)
{
    switch (m_renderSVGShape.geometryCodePath()) {
    case RectGeometryFastPath:
        context->fillRect(m_renderSVGShape.objectBoundingBox());
        break;
    case EllipseGeometryFastPath:
        context->fillEllipse(m_renderSVGShape.objectBoundingBox());
        break;
    default:
        context->fillPath(m_renderSVGShape.path());
    }
}

void SVGShapePainter::strokeShape(GraphicsContext* context)
{
    if (!m_renderSVGShape.style()->svgStyle().hasVisibleStroke())
        return;

    switch (m_renderSVGShape.geometryCodePath()) {
    case RectGeometryFastPath:
        context->strokeRect(m_renderSVGShape.objectBoundingBox(), m_renderSVGShape.strokeWidth());
        break;
    case EllipseGeometryFastPath:
        context->strokeEllipse(m_renderSVGShape.objectBoundingBox());
        break;
    default:
        ASSERT(m_renderSVGShape.hasPath());
        Path* usePath = &m_renderSVGShape.path();
        if (m_renderSVGShape.hasNonScalingStroke())
            usePath = m_renderSVGShape.nonScalingStrokePath(usePath, m_renderSVGShape.nonScalingStrokeTransform());
        context->strokePath(*usePath);
        strokeZeroLengthLineCaps(context);
    }
}

void SVGShapePainter::paintMarkers(const PaintInfo& paintInfo)
{
    const Vector<MarkerPosition>* markerPositions = m_renderSVGShape.markerPositions();
    if (!markerPositions || markerPositions->isEmpty())
        return;

    SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(&m_renderSVGShape);
    if (!resources)
        return;

    RenderSVGResourceMarker* markerStart = resources->markerStart();
    RenderSVGResourceMarker* markerMid = resources->markerMid();
    RenderSVGResourceMarker* markerEnd = resources->markerEnd();
    if (!markerStart && !markerMid && !markerEnd)
        return;

    float strokeWidth = m_renderSVGShape.strokeWidth();
    unsigned size = markerPositions->size();
    for (unsigned i = 0; i < size; ++i) {
        if (RenderSVGResourceMarker* marker = SVGMarkerData::markerForType((*markerPositions)[i].type, markerStart, markerMid, markerEnd))
            paintMarker(paintInfo, *marker, (*markerPositions)[i], strokeWidth);
    }
}

void SVGShapePainter::paintMarker(const PaintInfo& paintInfo, RenderSVGResourceMarker& marker, const MarkerPosition& position, float strokeWidth)
{
    // An empty viewBox disables rendering.
    SVGMarkerElement* markerElement = toSVGMarkerElement(marker.element());
    ASSERT(markerElement);
    if (markerElement->hasAttribute(SVGNames::viewBoxAttr) && markerElement->viewBox()->currentValue()->isValid() && markerElement->viewBox()->currentValue()->value().isEmpty())
        return;

    OwnPtr<DisplayItemList> displayItemList;
    if (RuntimeEnabledFeatures::slimmingPaintEnabled())
        displayItemList = DisplayItemList::create();
    GraphicsContext recordingContext(nullptr, displayItemList.get());
    recordingContext.beginRecording(m_renderSVGShape.paintInvalidationRectInLocalCoordinates());

    PaintInfo markerPaintInfo(paintInfo);
    markerPaintInfo.context = &recordingContext;
    {
        TransformRecorder transformRecorder(*markerPaintInfo.context, marker.displayItemClient(), marker.markerTransformation(position.origin, position.angle, strokeWidth));
        OwnPtr<FloatClipRecorder> clipRecorder;
        if (SVGLayoutSupport::isOverflowHidden(&marker))
            clipRecorder = adoptPtr(new FloatClipRecorder(recordingContext, marker.displayItemClient(), markerPaintInfo.phase, marker.viewport()));

        SVGContainerPainter(marker).paint(markerPaintInfo);
    }

    if (displayItemList)
        displayItemList->replay(&recordingContext);
    RefPtr<const SkPicture> recording = recordingContext.endRecording();
    paintInfo.context->drawPicture(recording.get());
}

void SVGShapePainter::strokeZeroLengthLineCaps(GraphicsContext* context)
{
    const Vector<FloatPoint>* zeroLengthLineCaps = m_renderSVGShape.zeroLengthLineCaps();
    if (!zeroLengthLineCaps || zeroLengthLineCaps->isEmpty())
        return;

    Path* usePath;
    AffineTransform nonScalingTransform;

    if (m_renderSVGShape.hasNonScalingStroke())
        nonScalingTransform = m_renderSVGShape.nonScalingStrokeTransform();

    GraphicsContextStateSaver stateSaver(*context, true);
    useStrokeStyleToFill(context);
    for (size_t i = 0; i < zeroLengthLineCaps->size(); ++i) {
        usePath = zeroLengthLinecapPath((*zeroLengthLineCaps)[i]);
        if (m_renderSVGShape.hasNonScalingStroke())
            usePath = m_renderSVGShape.nonScalingStrokePath(usePath, nonScalingTransform);
        context->fillPath(*usePath);
    }
}

Path* SVGShapePainter::zeroLengthLinecapPath(const FloatPoint& linecapPosition) const
{
    DEFINE_STATIC_LOCAL(Path, tempPath, ());

    tempPath.clear();
    if (m_renderSVGShape.style()->svgStyle().capStyle() == SquareCap)
        tempPath.addRect(RenderSVGPath::zeroLengthSubpathRect(linecapPosition, m_renderSVGShape.strokeWidth()));
    else
        tempPath.addEllipse(RenderSVGPath::zeroLengthSubpathRect(linecapPosition, m_renderSVGShape.strokeWidth()));

    return &tempPath;
}

} // namespace blink
<|endoftext|>