<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: documentinfo.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: kz $ $Date: 2007-10-09 15:34:23 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_comphelper.hxx"

#include "comphelper/documentinfo.hxx"
#include "comphelper/namedvaluecollection.hxx"

/** === begin UNO includes === **/
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
#include <com/sun/star/frame/XStorable.hpp>
/** === end UNO includes === **/

#include <cppuhelper/exc_hlp.hxx>

#include <osl/diagnose.h>
#include <osl/thread.h>

#include <boost/current_function.hpp>

//........................................................................
namespace comphelper {
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::uno::UNO_QUERY_THROW;
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::frame::XModel;
    using ::com::sun::star::frame::XController;
    using ::com::sun::star::beans::XPropertySet;
    using ::com::sun::star::document::XDocumentInfoSupplier;
    using ::com::sun::star::frame::XStorable;
    using ::com::sun::star::beans::XPropertySetInfo;
    /** === end UNO using === **/

    //====================================================================
    //= DocumentInfo
    //====================================================================
    //--------------------------------------------------------------------
    ::rtl::OUString DocumentInfo::getDocumentTitle( const Reference< XModel >& _rxDocument )
    {
        ::rtl::OUString sTitle;

        if ( !_rxDocument.is() )
            return sTitle;

        ::rtl::OUString sDocURL;
        try
        {
            // note that the following was roughly ripped from the former SvxScriptSelectorDialog::GetDocTitle
            // implementation. Additionally, heuristics from ucb/source/ucp/tdoc/tdoc_docmgr.cxx/getDocumentTitle
            // have been merged in.
            // I'm not really sure the steps make sense in this order ...
            const ::rtl::OUString sTitlePropName( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );

            sDocURL = _rxDocument->getURL();

            // 1. if the document is not saved, yet, check the frame title
            if ( sDocURL.getLength() == 0 )
            {
                Reference< XController > xCurrentController( _rxDocument->getCurrentController() );
                Reference< XPropertySet > xFrameProps;
                if ( xCurrentController.is() )
                    xFrameProps.set( xCurrentController->getFrame(), UNO_QUERY );
                Reference< XPropertySetInfo > xFramePSI;
                if ( xFrameProps.is() )
                    xFramePSI = xFrameProps->getPropertySetInfo();

                if ( xFramePSI.is() && xFramePSI->hasPropertyByName( sTitlePropName ) )
                {
                    OSL_VERIFY( xFrameProps->getPropertyValue( sTitlePropName ) >>= sTitle );
                    // process "UntitledX - YYYYYYYY" // to get UntitledX
                    sal_Int32 pos = 0;
                    sTitle = sTitle.getToken( 0, ' ', pos);
                }
            }

            if ( sTitle.getLength() != 0 )
                return sTitle;

            // 2. try the UNO DocumentInfo
            Reference< XDocumentInfoSupplier > xDIS( _rxDocument, UNO_QUERY );
            if ( xDIS.is() )
            {
                Reference< XPropertySet > xProp ( xDIS->getDocumentInfo(), UNO_QUERY_THROW );
                OSL_VERIFY( xProp->getPropertyValue( sTitlePropName ) >>= sTitle );
            }

            if ( sTitle.getLength() != 0 )
                return sTitle;

            // 3. try model arguments
            NamedValueCollection aModelArgs( _rxDocument->getArgs() );
            sTitle = aModelArgs.getOrDefault( "Title", sTitle );

            if ( sTitle.getLength() != 0 )
                return sTitle;

            // 4. try the last segment of the document URL
            // this formerly was an INetURLObject::getName( LAST_SEGMENT, true, DECODE_WITH_CHARSET ),
            // but since we moved this code to comphelper, we do not have access to an INetURLObject anymore
            // This heuristics here should be sufficient - finally, we will get an UNO title API in a not
            // too distant future (hopefully), then  this complete class is superfluous)
            if ( sDocURL.getLength() == 0 )
            {
                Reference< XStorable > xDocStorable( _rxDocument, UNO_QUERY_THROW );
                sDocURL = xDocStorable->getLocation();
            }
            sal_Int32 nLastSepPos = sDocURL.lastIndexOf( '/' );
            if ( ( nLastSepPos != -1 ) && ( nLastSepPos == sDocURL.getLength() - 1 ) )
            {
                sDocURL = sDocURL.copy( 0, nLastSepPos );
                nLastSepPos = sDocURL.lastIndexOf( '/' );
            }
            sTitle = sDocURL.copy( nLastSepPos + 1 );
        }
        catch ( const Exception& )
        {
            ::com::sun::star::uno::Any caught( ::cppu::getCaughtException() );
            ::rtl::OString sMessage( "caught an exception!" );
            sMessage += "ntype   : ";
            sMessage += ::rtl::OString( caught.getValueTypeName().getStr(), caught.getValueTypeName().getLength(), osl_getThreadTextEncoding() );
            sMessage += "nmessage: ";
            ::com::sun::star::uno::Exception exception;
            caught >>= exception;
            sMessage += ::rtl::OString( exception.Message.getStr(), exception.Message.getLength(), osl_getThreadTextEncoding() );
            sMessage += "nin function:n";
            sMessage += BOOST_CURRENT_FUNCTION;
            sMessage += "n";
            OSL_ENSURE( false, sMessage );
        }

        return sTitle;
    }

//........................................................................
} // namespace comphelper
//........................................................................
<commit_msg>INTEGRATION: CWS custommeta (1.2.32); FILE MERGED 2008/01/21 12:31:38 mst 1.2.32.1: - comphelper/source/misc/documentinfo.cxx:   + use XDocumentProperties instead of XDocumentInfo<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: documentinfo.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2008-02-26 15:13:56 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_comphelper.hxx"

#include "comphelper/documentinfo.hxx"
#include "comphelper/namedvaluecollection.hxx"

/** === begin UNO includes === **/
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <com/sun/star/document/XDocumentProperties.hpp>
#include <com/sun/star/frame/XStorable.hpp>
/** === end UNO includes === **/

#include <cppuhelper/exc_hlp.hxx>

#include <osl/diagnose.h>
#include <osl/thread.h>

#include <boost/current_function.hpp>

//........................................................................
namespace comphelper {
//........................................................................

    /** === begin UNO using === **/
    using ::com::sun::star::uno::Reference;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::uno::UNO_QUERY_THROW;
    using ::com::sun::star::uno::Exception;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::frame::XModel;
    using ::com::sun::star::frame::XController;
    using ::com::sun::star::beans::XPropertySet;
    using ::com::sun::star::document::XDocumentPropertiesSupplier;
    using ::com::sun::star::document::XDocumentProperties;
    using ::com::sun::star::frame::XStorable;
    using ::com::sun::star::beans::XPropertySetInfo;
    /** === end UNO using === **/

    //====================================================================
    //= DocumentInfo
    //====================================================================
    //--------------------------------------------------------------------
    ::rtl::OUString DocumentInfo::getDocumentTitle( const Reference< XModel >& _rxDocument )
    {
        ::rtl::OUString sTitle;

        if ( !_rxDocument.is() )
            return sTitle;

        ::rtl::OUString sDocURL;
        try
        {
            // note that the following was roughly ripped from the former SvxScriptSelectorDialog::GetDocTitle
            // implementation. Additionally, heuristics from ucb/source/ucp/tdoc/tdoc_docmgr.cxx/getDocumentTitle
            // have been merged in.
            // I'm not really sure the steps make sense in this order ...
            const ::rtl::OUString sTitlePropName( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );

            sDocURL = _rxDocument->getURL();

            // 1. if the document is not saved, yet, check the frame title
            if ( sDocURL.getLength() == 0 )
            {
                Reference< XController > xCurrentController( _rxDocument->getCurrentController() );
                Reference< XPropertySet > xFrameProps;
                if ( xCurrentController.is() )
                    xFrameProps.set( xCurrentController->getFrame(), UNO_QUERY );
                Reference< XPropertySetInfo > xFramePSI;
                if ( xFrameProps.is() )
                    xFramePSI = xFrameProps->getPropertySetInfo();

                if ( xFramePSI.is() && xFramePSI->hasPropertyByName( sTitlePropName ) )
                {
                    OSL_VERIFY( xFrameProps->getPropertyValue( sTitlePropName ) >>= sTitle );
                    // process "UntitledX - YYYYYYYY" // to get UntitledX
                    sal_Int32 pos = 0;
                    sTitle = sTitle.getToken( 0, ' ', pos);
                }
            }

            if ( sTitle.getLength() != 0 )
                return sTitle;

            // 2. try the UNO DocumentInfo
            Reference< XDocumentPropertiesSupplier > xDPS( _rxDocument, UNO_QUERY );
            if ( xDPS.is() )
            {
                Reference< XDocumentProperties > xDocProps (
                    xDPS->getDocumentProperties(), UNO_QUERY_THROW );
                OSL_ENSURE(xDocProps.is(), "no DocumentProperties");
                sTitle = xDocProps->getTitle();
            }

            if ( sTitle.getLength() != 0 )
                return sTitle;

            // 3. try model arguments
            NamedValueCollection aModelArgs( _rxDocument->getArgs() );
            sTitle = aModelArgs.getOrDefault( "Title", sTitle );

            if ( sTitle.getLength() != 0 )
                return sTitle;

            // 4. try the last segment of the document URL
            // this formerly was an INetURLObject::getName( LAST_SEGMENT, true, DECODE_WITH_CHARSET ),
            // but since we moved this code to comphelper, we do not have access to an INetURLObject anymore
            // This heuristics here should be sufficient - finally, we will get an UNO title API in a not
            // too distant future (hopefully), then  this complete class is superfluous)
            if ( sDocURL.getLength() == 0 )
            {
                Reference< XStorable > xDocStorable( _rxDocument, UNO_QUERY_THROW );
                sDocURL = xDocStorable->getLocation();
            }
            sal_Int32 nLastSepPos = sDocURL.lastIndexOf( '/' );
            if ( ( nLastSepPos != -1 ) && ( nLastSepPos == sDocURL.getLength() - 1 ) )
            {
                sDocURL = sDocURL.copy( 0, nLastSepPos );
                nLastSepPos = sDocURL.lastIndexOf( '/' );
            }
            sTitle = sDocURL.copy( nLastSepPos + 1 );
        }
        catch ( const Exception& )
        {
            ::com::sun::star::uno::Any caught( ::cppu::getCaughtException() );
            ::rtl::OString sMessage( "caught an exception!" );
            sMessage += "ntype   : ";
            sMessage += ::rtl::OString( caught.getValueTypeName().getStr(), caught.getValueTypeName().getLength(), osl_getThreadTextEncoding() );
            sMessage += "nmessage: ";
            ::com::sun::star::uno::Exception exception;
            caught >>= exception;
            sMessage += ::rtl::OString( exception.Message.getStr(), exception.Message.getLength(), osl_getThreadTextEncoding() );
            sMessage += "nin function:n";
            sMessage += BOOST_CURRENT_FUNCTION;
            sMessage += "n";
            OSL_ENSURE( false, sMessage );
        }

        return sTitle;
    }

//........................................................................
} // namespace comphelper
//........................................................................
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <string>
#include <set>

#include "plugin.hxx"

// Find places where we call a method with values == the values specified in the parameter defaults.
// i.e. where the code might as well not specify anything.

namespace {

class DefaultParams:
    public RecursiveASTVisitor<DefaultParams>, public loplugin::Plugin
{
public:
    explicit DefaultParams(InstantiationData const & data): Plugin(data) {}

    virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }

    bool VisitCallExpr(CallExpr * callExpr);
};

bool DefaultParams::VisitCallExpr(CallExpr * callExpr) {
    if (ignoreLocation(callExpr)) {
        return true;
    }
    if (callExpr->getNumArgs() == 0) {
        return true;
    }
    if (callExpr->getDirectCallee() == nullptr) {
        return true;
    }
    const FunctionDecl* functionDecl = callExpr->getDirectCallee()->getCanonicalDecl();
    unsigned i = callExpr->getNumArgs() - 1;
    Expr* arg = callExpr->getArg(i);
    // variadic functions
    if (i >= functionDecl->getNumParams()) {
        return true;
    }
    if (arg->isDefaultArgument()) {
        return true;
    }
    // ignore this, it seems to trigger an infinite recursion
    if (isa<UnaryExprOrTypeTraitExpr>(arg))
        return true;
    const ParmVarDecl* parmVarDecl = functionDecl->getParamDecl(i);
    if (!parmVarDecl->hasDefaultArg()
        || parmVarDecl->hasUninstantiatedDefaultArg())
    {
        return true;
    }
    const Expr* defaultArgExpr = parmVarDecl->getDefaultArg();
    if (defaultArgExpr &&
        defaultArgExpr->getType()->isIntegralType(compiler.getASTContext()))
    {
        APSInt x1, x2;
        if (arg->EvaluateAsInt(x1, compiler.getASTContext()) &&
            defaultArgExpr->EvaluateAsInt(x2, compiler.getASTContext()) &&
            x1 == x2)
        {
            report(
                DiagnosticsEngine::Warning,
                "not necessary to pass this argument, it defaults to the same value",
                arg->getSourceRange().getBegin())
              << arg->getSourceRange();
            /*report(
                DiagnosticsEngine::Warning,
                "default method parameter declaration here",
                parmVarDecl->getSourceRange().getBegin())
              << parmVarDecl->getSourceRange();*/
        }
    }
    return true;
}

loplugin::Plugin::Registration< DefaultParams > X("defaultparams", false);

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Enable loplugin:defaultparams<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <string>
#include <set>

#include "plugin.hxx"

// Find places where we call a method with values == the values specified in the parameter defaults.
// i.e. where the code might as well not specify anything.

namespace {

class DefaultParams:
    public RecursiveASTVisitor<DefaultParams>, public loplugin::Plugin
{
public:
    explicit DefaultParams(InstantiationData const & data): Plugin(data) {}

    virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }

    bool VisitCallExpr(CallExpr * callExpr);
};

bool DefaultParams::VisitCallExpr(CallExpr * callExpr) {
    if (ignoreLocation(callExpr)) {
        return true;
    }
    if (callExpr->getNumArgs() == 0) {
        return true;
    }
    if (callExpr->getDirectCallee() == nullptr) {
        return true;
    }
    const FunctionDecl* functionDecl = callExpr->getDirectCallee()->getCanonicalDecl();
    unsigned i = callExpr->getNumArgs() - 1;
    Expr* arg = callExpr->getArg(i);
    // variadic functions
    if (i >= functionDecl->getNumParams()) {
        return true;
    }
    if (arg->isDefaultArgument()) {
        return true;
    }
    // ignore this, it seems to trigger an infinite recursion
    if (isa<UnaryExprOrTypeTraitExpr>(arg))
        return true;
    const ParmVarDecl* parmVarDecl = functionDecl->getParamDecl(i);
    if (!parmVarDecl->hasDefaultArg()
        || parmVarDecl->hasUninstantiatedDefaultArg())
    {
        return true;
    }
    const Expr* defaultArgExpr = parmVarDecl->getDefaultArg();
    if (defaultArgExpr &&
        defaultArgExpr->getType()->isIntegralType(compiler.getASTContext()))
    {
        APSInt x1, x2;
        if (arg->EvaluateAsInt(x1, compiler.getASTContext()) &&
            defaultArgExpr->EvaluateAsInt(x2, compiler.getASTContext()) &&
            x1 == x2)
        {
            report(
                DiagnosticsEngine::Warning,
                "not necessary to pass this argument, it defaults to the same value",
                arg->getSourceRange().getBegin())
              << arg->getSourceRange();
            /*report(
                DiagnosticsEngine::Warning,
                "default method parameter declaration here",
                parmVarDecl->getSourceRange().getBegin())
              << parmVarDecl->getSourceRange();*/
        }
    }
    return true;
}

loplugin::Plugin::Registration< DefaultParams > X("defaultparams");

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "app/clipboard/clipboard.h"

#include <gtk/gtk.h>
#include <map>
#include <set>
#include <string>
#include <utility>

#include "base/file_path.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "app/gtk_util.h"
#include "base/utf_string_conversions.h"
#include "gfx/size.h"

namespace {

const char kMimeBmp[] = "image/bmp";
const char kMimeHtml[] = "text/html";
const char kMimeText[] = "text/plain";
const char kMimeURI[] = "text/uri-list";
const char kMimeWebkitSmartPaste[] = "chromium/x-webkit-paste";

std::string GdkAtomToString(const GdkAtom& atom) {
  gchar* name = gdk_atom_name(atom);
  std::string rv(name);
  g_free(name);
  return rv;
}

GdkAtom StringToGdkAtom(const std::string& str) {
  return gdk_atom_intern(str.c_str(), FALSE);
}

// GtkClipboardGetFunc callback.
// GTK will call this when an application wants data we copied to the clipboard.
void GetData(GtkClipboard* clipboard,
             GtkSelectionData* selection_data,
             guint info,
             gpointer user_data) {
  Clipboard::TargetMap* data_map =
      reinterpret_cast<Clipboard::TargetMap*>(user_data);

  std::string target_string = GdkAtomToString(selection_data->target);
  Clipboard::TargetMap::iterator iter = data_map->find(target_string);

  if (iter == data_map->end())
    return;

  if (target_string == kMimeBmp) {
    gtk_selection_data_set_pixbuf(selection_data,
        reinterpret_cast<GdkPixbuf*>(iter->second.first));
  } else if (target_string == kMimeURI) {
    gchar* uri_list[2];
    uri_list[0] = reinterpret_cast<gchar*>(iter->second.first);
    uri_list[1] = NULL;
    gtk_selection_data_set_uris(selection_data, uri_list);
  } else {
    gtk_selection_data_set(selection_data, selection_data->target, 8,
                           reinterpret_cast<guchar*>(iter->second.first),
                           iter->second.second);
  }
}

// GtkClipboardClearFunc callback.
// We are guaranteed this will be called exactly once for each call to
// gtk_clipboard_set_with_data.
void ClearData(GtkClipboard* clipboard,
               gpointer user_data) {
  Clipboard::TargetMap* map =
      reinterpret_cast<Clipboard::TargetMap*>(user_data);
  // The same data may be inserted under multiple keys, so use a set to
  // uniq them.
  std::set<char*> ptrs;

  for (Clipboard::TargetMap::iterator iter = map->begin();
       iter != map->end(); ++iter) {
    if (iter->first == kMimeBmp)
      g_object_unref(reinterpret_cast<GdkPixbuf*>(iter->second.first));
    else
      ptrs.insert(iter->second.first);
  }

  for (std::set<char*>::iterator iter = ptrs.begin();
       iter != ptrs.end(); ++iter) {
    delete[] *iter;
  }

  delete map;
}

// Called on GdkPixbuf destruction; see WriteBitmap().
void GdkPixbufFree(guchar* pixels, gpointer data) {
  free(pixels);
}

}  // namespace

Clipboard::Clipboard() {
  clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
  primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
}

Clipboard::~Clipboard() {
  // TODO(estade): do we want to save clipboard data after we exit?
  // gtk_clipboard_set_can_store and gtk_clipboard_store work
  // but have strangely awful performance.
}

void Clipboard::WriteObjects(const ObjectMap& objects) {
  clipboard_data_ = new TargetMap();

  for (ObjectMap::const_iterator iter = objects.begin();
       iter != objects.end(); ++iter) {
    DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
  }

  SetGtkClipboard();
}

// When a URL is copied from a render view context menu (via "copy link
// location", for example), we additionally stick it in the X clipboard. This
// matches other linux browsers.
void Clipboard::DidWriteURL(const std::string& utf8_text) {
  gtk_clipboard_set_text(primary_selection_, utf8_text.c_str(),
                         utf8_text.length());
}

// Take ownership of the GTK clipboard and inform it of the targets we support.
void Clipboard::SetGtkClipboard() {
  scoped_array<GtkTargetEntry> targets(
      new GtkTargetEntry[clipboard_data_->size()]);

  int i = 0;
  for (Clipboard::TargetMap::iterator iter = clipboard_data_->begin();
       iter != clipboard_data_->end(); ++iter, ++i) {
    targets[i].target = const_cast<char*>(iter->first.c_str());
    targets[i].flags = 0;
    targets[i].info = 0;
  }

  gtk_clipboard_set_with_data(clipboard_, targets.get(),
                              clipboard_data_->size(),
                              GetData, ClearData,
                              clipboard_data_);

  // clipboard_data_ now owned by the GtkClipboard.
  clipboard_data_ = NULL;
}

void Clipboard::WriteText(const char* text_data, size_t text_len) {
  char* data = new char[text_len + 1];
  memcpy(data, text_data, text_len);
  data[text_len] = '\0';

  InsertMapping(kMimeText, data, text_len);
  InsertMapping("TEXT", data, text_len);
  InsertMapping("STRING", data, text_len);
  InsertMapping("UTF8_STRING", data, text_len);
  InsertMapping("COMPOUND_TEXT", data, text_len);
}

void Clipboard::WriteHTML(const char* markup_data,
                          size_t markup_len,
                          const char* url_data,
                          size_t url_len) {
  // TODO(estade): We need to expand relative links with |url_data|.
  static const char* html_prefix = "<meta http-equiv=\"content-type\" "
                                   "content=\"text/html; charset=utf-8\">";
  size_t html_prefix_len = strlen(html_prefix);
  size_t total_len = html_prefix_len + markup_len + 1;

  char* data = new char[total_len];
  snprintf(data, total_len, "%s", html_prefix);
  memcpy(data + html_prefix_len, markup_data, markup_len);
  data[total_len - 1] = '\0';

  InsertMapping(kMimeHtml, data, total_len);
}

// Write an extra flavor that signifies WebKit was the last to modify the
// pasteboard. This flavor has no data.
void Clipboard::WriteWebSmartPaste() {
  InsertMapping(kMimeWebkitSmartPaste, NULL, 0);
}

void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) {
  const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data);

  guchar* data =
      gtk_util::BGRAToRGBA(reinterpret_cast<const uint8_t*>(pixel_data),
                           size->width(), size->height(), 0);

  GdkPixbuf* pixbuf =
      gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE,
                               8, size->width(), size->height(),
                               size->width() * 4, GdkPixbufFree, NULL);
  // We store the GdkPixbuf*, and the size_t half of the pair is meaningless.
  // Note that this contrasts with the vast majority of entries in our target
  // map, which directly store the data and its length.
  InsertMapping(kMimeBmp, reinterpret_cast<char*>(pixbuf), 0);
}

void Clipboard::WriteBookmark(const char* title_data, size_t title_len,
                              const char* url_data, size_t url_len) {
  // Write as a URI.
  char* data = new char[url_len + 1];
  memcpy(data, url_data, url_len);
  data[url_len] = '\0';
  InsertMapping(kMimeURI, data, url_len + 1);
}

void Clipboard::WriteData(const char* format_name, size_t format_len,
                          const char* data_data, size_t data_len) {
  char* data = new char[data_len];
  memcpy(data, data_data, data_len);
  std::string format(format_name, format_len);
  // We assume that certain mapping types are only written by trusted code.
  // Therefore we must upkeep their integrity.
  if (format == kMimeBmp || format == kMimeURI)
    return;
  InsertMapping(format.c_str(), data, data_len);
}

// We do not use gtk_clipboard_wait_is_target_available because of
// a bug with the gtk clipboard. It caches the available targets
// and does not always refresh the cache when it is appropriate.
bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format,
                                  Clipboard::Buffer buffer) const {
  GtkClipboard* clipboard = LookupBackingClipboard(buffer);
  if (clipboard == NULL)
    return false;

  bool format_is_plain_text = GetPlainTextFormatType() == format;
  if (format_is_plain_text) {
    // This tries a number of common text targets.
    if (gtk_clipboard_wait_is_text_available(clipboard))
      return true;
  }

  bool retval = false;
  GdkAtom* targets = NULL;
  GtkSelectionData* data =
      gtk_clipboard_wait_for_contents(clipboard,
                                      gdk_atom_intern("TARGETS", false));

  if (!data)
    return false;

  int num = 0;
  gtk_selection_data_get_targets(data, &targets, &num);

  // Some programs post data to the clipboard without any targets. If this is
  // the case we attempt to make sense of the contents as text. This is pretty
  // unfortunate since it means we have to actually copy the data to see if it
  // is available, but at least this path shouldn't be hit for conforming
  // programs.
  if (num <= 0) {
    if (format_is_plain_text) {
      gchar* text = gtk_clipboard_wait_for_text(clipboard);
      if (text) {
        g_free(text);
        retval = true;
      }
    }
  }

  GdkAtom format_atom = StringToGdkAtom(format);

  for (int i = 0; i < num; i++) {
    if (targets[i] == format_atom) {
      retval = true;
      break;
    }
  }

  g_free(targets);
  gtk_selection_data_free(data);

  return retval;
}

bool Clipboard::IsFormatAvailableByString(const std::string& format,
                                          Clipboard::Buffer buffer) const {
  return IsFormatAvailable(format, buffer);
}

void Clipboard::ReadText(Clipboard::Buffer buffer, string16* result) const {
  GtkClipboard* clipboard = LookupBackingClipboard(buffer);
  if (clipboard == NULL)
    return;

  result->clear();
  gchar* text = gtk_clipboard_wait_for_text(clipboard);

  if (text == NULL)
    return;

  // TODO(estade): do we want to handle the possible error here?
  UTF8ToUTF16(text, strlen(text), result);
  g_free(text);
}

void Clipboard::ReadAsciiText(Clipboard::Buffer buffer,
                              std::string* result) const {
  GtkClipboard* clipboard = LookupBackingClipboard(buffer);
  if (clipboard == NULL)
    return;

  result->clear();
  gchar* text = gtk_clipboard_wait_for_text(clipboard);

  if (text == NULL)
    return;

  result->assign(text);
  g_free(text);
}

void Clipboard::ReadFile(FilePath* file) const {
  *file = FilePath();
}

// TODO(estade): handle different charsets.
// TODO(port): set *src_url.
void Clipboard::ReadHTML(Clipboard::Buffer buffer, string16* markup,
                         std::string* src_url) const {
  GtkClipboard* clipboard = LookupBackingClipboard(buffer);
  if (clipboard == NULL)
    return;
  markup->clear();

  GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard,
      StringToGdkAtom(GetHtmlFormatType()));

  if (!data)
    return;

  // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
  // UTF-16, otherwise assume UTF-8.
  if (data->length >= 2 &&
      reinterpret_cast<uint16_t*>(data->data)[0] == 0xFEFF) {
    markup->assign(reinterpret_cast<uint16_t*>(data->data) + 1,
                   (data->length / 2) - 1);
  } else {
    UTF8ToUTF16(reinterpret_cast<char*>(data->data), data->length, markup);
  }

  gtk_selection_data_free(data);
}

void Clipboard::ReadBookmark(string16* title, std::string* url) const {
  // TODO(estade): implement this.
  NOTIMPLEMENTED();
}

void Clipboard::ReadData(const std::string& format, std::string* result) {
  GtkSelectionData* data =
      gtk_clipboard_wait_for_contents(clipboard_, StringToGdkAtom(format));
  if (!data)
    return;
  result->assign(reinterpret_cast<char*>(data->data), data->length);
  gtk_selection_data_free(data);
}

// static
Clipboard::FormatType Clipboard::GetPlainTextFormatType() {
  return GdkAtomToString(GDK_TARGET_STRING);
}

// static
Clipboard::FormatType Clipboard::GetPlainTextWFormatType() {
  return GetPlainTextFormatType();
}

// static
Clipboard::FormatType Clipboard::GetHtmlFormatType() {
  return std::string(kMimeHtml);
}

// static
Clipboard::FormatType Clipboard::GetBitmapFormatType() {
  return std::string(kMimeBmp);
}

// static
Clipboard::FormatType Clipboard::GetWebKitSmartPasteFormatType() {
  return std::string(kMimeWebkitSmartPaste);
}

void Clipboard::InsertMapping(const char* key,
                              char* data,
                              size_t data_len) {
  DCHECK(clipboard_data_->find(key) == clipboard_data_->end());
  (*clipboard_data_)[key] = std::make_pair(data, data_len);
}

GtkClipboard* Clipboard::LookupBackingClipboard(Buffer clipboard) const {
  switch (clipboard) {
    case BUFFER_STANDARD:
      return clipboard_;
    case BUFFER_SELECTION:
      return primary_selection_;
    default:
      NOTREACHED();
      return NULL;
  }
}
<commit_msg>GTK - don't paste a garbage text/html character.<commit_after>// Copyright (c) 2010 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 "app/clipboard/clipboard.h"

#include <gtk/gtk.h>
#include <map>
#include <set>
#include <string>
#include <utility>

#include "base/file_path.h"
#include "base/logging.h"
#include "base/scoped_ptr.h"
#include "app/gtk_util.h"
#include "base/utf_string_conversions.h"
#include "gfx/size.h"

namespace {

const char kMimeBmp[] = "image/bmp";
const char kMimeHtml[] = "text/html";
const char kMimeText[] = "text/plain";
const char kMimeURI[] = "text/uri-list";
const char kMimeWebkitSmartPaste[] = "chromium/x-webkit-paste";

std::string GdkAtomToString(const GdkAtom& atom) {
  gchar* name = gdk_atom_name(atom);
  std::string rv(name);
  g_free(name);
  return rv;
}

GdkAtom StringToGdkAtom(const std::string& str) {
  return gdk_atom_intern(str.c_str(), FALSE);
}

// GtkClipboardGetFunc callback.
// GTK will call this when an application wants data we copied to the clipboard.
void GetData(GtkClipboard* clipboard,
             GtkSelectionData* selection_data,
             guint info,
             gpointer user_data) {
  Clipboard::TargetMap* data_map =
      reinterpret_cast<Clipboard::TargetMap*>(user_data);

  std::string target_string = GdkAtomToString(selection_data->target);
  Clipboard::TargetMap::iterator iter = data_map->find(target_string);

  if (iter == data_map->end())
    return;

  if (target_string == kMimeBmp) {
    gtk_selection_data_set_pixbuf(selection_data,
        reinterpret_cast<GdkPixbuf*>(iter->second.first));
  } else if (target_string == kMimeURI) {
    gchar* uri_list[2];
    uri_list[0] = reinterpret_cast<gchar*>(iter->second.first);
    uri_list[1] = NULL;
    gtk_selection_data_set_uris(selection_data, uri_list);
  } else {
    gtk_selection_data_set(selection_data, selection_data->target, 8,
                           reinterpret_cast<guchar*>(iter->second.first),
                           iter->second.second);
  }
}

// GtkClipboardClearFunc callback.
// We are guaranteed this will be called exactly once for each call to
// gtk_clipboard_set_with_data.
void ClearData(GtkClipboard* clipboard,
               gpointer user_data) {
  Clipboard::TargetMap* map =
      reinterpret_cast<Clipboard::TargetMap*>(user_data);
  // The same data may be inserted under multiple keys, so use a set to
  // uniq them.
  std::set<char*> ptrs;

  for (Clipboard::TargetMap::iterator iter = map->begin();
       iter != map->end(); ++iter) {
    if (iter->first == kMimeBmp)
      g_object_unref(reinterpret_cast<GdkPixbuf*>(iter->second.first));
    else
      ptrs.insert(iter->second.first);
  }

  for (std::set<char*>::iterator iter = ptrs.begin();
       iter != ptrs.end(); ++iter) {
    delete[] *iter;
  }

  delete map;
}

// Called on GdkPixbuf destruction; see WriteBitmap().
void GdkPixbufFree(guchar* pixels, gpointer data) {
  free(pixels);
}

}  // namespace

Clipboard::Clipboard() {
  clipboard_ = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
  primary_selection_ = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
}

Clipboard::~Clipboard() {
  // TODO(estade): do we want to save clipboard data after we exit?
  // gtk_clipboard_set_can_store and gtk_clipboard_store work
  // but have strangely awful performance.
}

void Clipboard::WriteObjects(const ObjectMap& objects) {
  clipboard_data_ = new TargetMap();

  for (ObjectMap::const_iterator iter = objects.begin();
       iter != objects.end(); ++iter) {
    DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
  }

  SetGtkClipboard();
}

// When a URL is copied from a render view context menu (via "copy link
// location", for example), we additionally stick it in the X clipboard. This
// matches other linux browsers.
void Clipboard::DidWriteURL(const std::string& utf8_text) {
  gtk_clipboard_set_text(primary_selection_, utf8_text.c_str(),
                         utf8_text.length());
}

// Take ownership of the GTK clipboard and inform it of the targets we support.
void Clipboard::SetGtkClipboard() {
  scoped_array<GtkTargetEntry> targets(
      new GtkTargetEntry[clipboard_data_->size()]);

  int i = 0;
  for (Clipboard::TargetMap::iterator iter = clipboard_data_->begin();
       iter != clipboard_data_->end(); ++iter, ++i) {
    targets[i].target = const_cast<char*>(iter->first.c_str());
    targets[i].flags = 0;
    targets[i].info = 0;
  }

  gtk_clipboard_set_with_data(clipboard_, targets.get(),
                              clipboard_data_->size(),
                              GetData, ClearData,
                              clipboard_data_);

  // clipboard_data_ now owned by the GtkClipboard.
  clipboard_data_ = NULL;
}

void Clipboard::WriteText(const char* text_data, size_t text_len) {
  char* data = new char[text_len];
  memcpy(data, text_data, text_len);

  InsertMapping(kMimeText, data, text_len);
  InsertMapping("TEXT", data, text_len);
  InsertMapping("STRING", data, text_len);
  InsertMapping("UTF8_STRING", data, text_len);
  InsertMapping("COMPOUND_TEXT", data, text_len);
}

void Clipboard::WriteHTML(const char* markup_data,
                          size_t markup_len,
                          const char* url_data,
                          size_t url_len) {
  // TODO(estade): We need to expand relative links with |url_data|.
  static const char* html_prefix = "<meta http-equiv=\"content-type\" "
                                   "content=\"text/html; charset=utf-8\">";
  size_t html_prefix_len = strlen(html_prefix);
  size_t total_len = html_prefix_len + markup_len + 1;

  char* data = new char[total_len];
  snprintf(data, total_len, "%s", html_prefix);
  memcpy(data + html_prefix_len, markup_data, markup_len);
  // Some programs expect NULL-terminated data. See http://crbug.com/42624
  data[total_len - 1] = '\0';

  InsertMapping(kMimeHtml, data, total_len);
}

// Write an extra flavor that signifies WebKit was the last to modify the
// pasteboard. This flavor has no data.
void Clipboard::WriteWebSmartPaste() {
  InsertMapping(kMimeWebkitSmartPaste, NULL, 0);
}

void Clipboard::WriteBitmap(const char* pixel_data, const char* size_data) {
  const gfx::Size* size = reinterpret_cast<const gfx::Size*>(size_data);

  guchar* data =
      gtk_util::BGRAToRGBA(reinterpret_cast<const uint8_t*>(pixel_data),
                           size->width(), size->height(), 0);

  GdkPixbuf* pixbuf =
      gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE,
                               8, size->width(), size->height(),
                               size->width() * 4, GdkPixbufFree, NULL);
  // We store the GdkPixbuf*, and the size_t half of the pair is meaningless.
  // Note that this contrasts with the vast majority of entries in our target
  // map, which directly store the data and its length.
  InsertMapping(kMimeBmp, reinterpret_cast<char*>(pixbuf), 0);
}

void Clipboard::WriteBookmark(const char* title_data, size_t title_len,
                              const char* url_data, size_t url_len) {
  // Write as a URI.
  char* data = new char[url_len + 1];
  memcpy(data, url_data, url_len);
  data[url_len] = '\0';
  InsertMapping(kMimeURI, data, url_len + 1);
}

void Clipboard::WriteData(const char* format_name, size_t format_len,
                          const char* data_data, size_t data_len) {
  char* data = new char[data_len];
  memcpy(data, data_data, data_len);
  std::string format(format_name, format_len);
  // We assume that certain mapping types are only written by trusted code.
  // Therefore we must upkeep their integrity.
  if (format == kMimeBmp || format == kMimeURI)
    return;
  InsertMapping(format.c_str(), data, data_len);
}

// We do not use gtk_clipboard_wait_is_target_available because of
// a bug with the gtk clipboard. It caches the available targets
// and does not always refresh the cache when it is appropriate.
bool Clipboard::IsFormatAvailable(const Clipboard::FormatType& format,
                                  Clipboard::Buffer buffer) const {
  GtkClipboard* clipboard = LookupBackingClipboard(buffer);
  if (clipboard == NULL)
    return false;

  bool format_is_plain_text = GetPlainTextFormatType() == format;
  if (format_is_plain_text) {
    // This tries a number of common text targets.
    if (gtk_clipboard_wait_is_text_available(clipboard))
      return true;
  }

  bool retval = false;
  GdkAtom* targets = NULL;
  GtkSelectionData* data =
      gtk_clipboard_wait_for_contents(clipboard,
                                      gdk_atom_intern("TARGETS", false));

  if (!data)
    return false;

  int num = 0;
  gtk_selection_data_get_targets(data, &targets, &num);

  // Some programs post data to the clipboard without any targets. If this is
  // the case we attempt to make sense of the contents as text. This is pretty
  // unfortunate since it means we have to actually copy the data to see if it
  // is available, but at least this path shouldn't be hit for conforming
  // programs.
  if (num <= 0) {
    if (format_is_plain_text) {
      gchar* text = gtk_clipboard_wait_for_text(clipboard);
      if (text) {
        g_free(text);
        retval = true;
      }
    }
  }

  GdkAtom format_atom = StringToGdkAtom(format);

  for (int i = 0; i < num; i++) {
    if (targets[i] == format_atom) {
      retval = true;
      break;
    }
  }

  g_free(targets);
  gtk_selection_data_free(data);

  return retval;
}

bool Clipboard::IsFormatAvailableByString(const std::string& format,
                                          Clipboard::Buffer buffer) const {
  return IsFormatAvailable(format, buffer);
}

void Clipboard::ReadText(Clipboard::Buffer buffer, string16* result) const {
  GtkClipboard* clipboard = LookupBackingClipboard(buffer);
  if (clipboard == NULL)
    return;

  result->clear();
  gchar* text = gtk_clipboard_wait_for_text(clipboard);

  if (text == NULL)
    return;

  // TODO(estade): do we want to handle the possible error here?
  UTF8ToUTF16(text, strlen(text), result);
  g_free(text);
}

void Clipboard::ReadAsciiText(Clipboard::Buffer buffer,
                              std::string* result) const {
  GtkClipboard* clipboard = LookupBackingClipboard(buffer);
  if (clipboard == NULL)
    return;

  result->clear();
  gchar* text = gtk_clipboard_wait_for_text(clipboard);

  if (text == NULL)
    return;

  result->assign(text);
  g_free(text);
}

void Clipboard::ReadFile(FilePath* file) const {
  *file = FilePath();
}

// TODO(estade): handle different charsets.
// TODO(port): set *src_url.
void Clipboard::ReadHTML(Clipboard::Buffer buffer, string16* markup,
                         std::string* src_url) const {
  GtkClipboard* clipboard = LookupBackingClipboard(buffer);
  if (clipboard == NULL)
    return;
  markup->clear();

  GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard,
      StringToGdkAtom(GetHtmlFormatType()));

  if (!data)
    return;

  // If the data starts with 0xFEFF, i.e., Byte Order Mark, assume it is
  // UTF-16, otherwise assume UTF-8.
  if (data->length >= 2 &&
      reinterpret_cast<uint16_t*>(data->data)[0] == 0xFEFF) {
    markup->assign(reinterpret_cast<uint16_t*>(data->data) + 1,
                   (data->length / 2) - 1);
  } else {
    UTF8ToUTF16(reinterpret_cast<char*>(data->data), data->length, markup);
  }

  // If there is a terminating NULL, drop it.
  if (markup->at(markup->length() - 1) == '\0')
    markup->resize(markup->length() - 1);

  gtk_selection_data_free(data);
}

void Clipboard::ReadBookmark(string16* title, std::string* url) const {
  // TODO(estade): implement this.
  NOTIMPLEMENTED();
}

void Clipboard::ReadData(const std::string& format, std::string* result) {
  GtkSelectionData* data =
      gtk_clipboard_wait_for_contents(clipboard_, StringToGdkAtom(format));
  if (!data)
    return;
  result->assign(reinterpret_cast<char*>(data->data), data->length);
  gtk_selection_data_free(data);
}

// static
Clipboard::FormatType Clipboard::GetPlainTextFormatType() {
  return GdkAtomToString(GDK_TARGET_STRING);
}

// static
Clipboard::FormatType Clipboard::GetPlainTextWFormatType() {
  return GetPlainTextFormatType();
}

// static
Clipboard::FormatType Clipboard::GetHtmlFormatType() {
  return std::string(kMimeHtml);
}

// static
Clipboard::FormatType Clipboard::GetBitmapFormatType() {
  return std::string(kMimeBmp);
}

// static
Clipboard::FormatType Clipboard::GetWebKitSmartPasteFormatType() {
  return std::string(kMimeWebkitSmartPaste);
}

void Clipboard::InsertMapping(const char* key,
                              char* data,
                              size_t data_len) {
  DCHECK(clipboard_data_->find(key) == clipboard_data_->end());
  (*clipboard_data_)[key] = std::make_pair(data, data_len);
}

GtkClipboard* Clipboard::LookupBackingClipboard(Buffer clipboard) const {
  switch (clipboard) {
    case BUFFER_STANDARD:
      return clipboard_;
    case BUFFER_SELECTION:
      return primary_selection_;
    default:
      NOTREACHED();
      return NULL;
  }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdlib>
#include <cstring>
#include "database.hpp"
#include "transaction.hpp"
#include "customer.hpp"

using namespace std;

void Database::initFile(const char* filename, fstream& fs) {
    char magic[8]="CINEMAN";
    fs.open(filename,fstream::in);
    if(fs.fail()) {
        fs.close();
        fs.open(filename,fstream::out|fstream::binary);
        fs.write(magic,8);
        for(int i=0;i<4;i++) {fs.put(0);}
    }
    fs.close();
    fs.open(filename,fstream::in|fstream::out|fstream::binary);
    fs.seekg(0);
    char fmagic[8];
    fs.read(fmagic,8);
    if(strcmp(fmagic,magic)!=0) {
        cout << "Error: Invalid or corrupted database file!" << endl;
        exit(EXIT_FAILURE);
    }
}

Database::Database() {
    initFile("members.db",this->membersFile);
    initFile("sales.db",this->salesFile);
    loadMembers();
    loadSales();
}

Database::~Database() {
    membersFile.close();
    salesFile.close();
}

void Database::loadMembers() {
    int memberCount;
    membersFile.seekg(8);
    membersFile.read((char*)&memberCount,sizeof(int));
    for(int i=0;i<memberCount;i++) {
        char memberType;
        customerStruct cStruct;
        membersFile.read(&memberType,1);
        membersFile.read((char*)&cStruct,sizeof(customerStruct));
        Customer *c;
        switch(memberType) {
            case 1:
                c=new MemberGold(i,&cStruct);
                break;
            case 2:
                c=new MemberPlatinum(i,&cStruct);
                break;
            default:
                cout << "Error reading database: Unknown member type at ID: " << i << endl;
                exit(EXIT_FAILURE);
                break;
        }
        members.push_back((Customer*)c);
    }
}

void Database::loadSales() {
    int salesCount;
    salesFile.seekg(8);
    salesFile.read((char*)&salesCount,sizeof(int));
    for(int i=0;i<salesCount;i++) {
        cout << i << endl;
        saleStruct* sStruct=new saleStruct;
        salesFile.read((char*)sStruct,sizeof(saleStruct));
        sales.push_back(sStruct);
    }
}

void Database::addMember(Customer* c) {
    int newID=members.size()+1;
    members.push_back(c);
    customerStruct cStruct=c->getStruct();
    char memberType=c->getType();
    membersFile.seekp(8);
    membersFile.write((char*)&newID,sizeof(int));
    membersFile.seekp(0,ios_base::end);
    membersFile.write(&memberType,1);
    membersFile.write((char*)&cStruct,sizeof(customerStruct));
    membersFile.flush();
}

void Database::addSale(saleStruct* sStruct) {
    int newID=sales.size()+1;
    sales.push_back(sStruct);
    salesFile.seekp(8);
    salesFile.write((char*)&newID,sizeof(int));
    salesFile.seekp(0,ios_base::end);
    salesFile.write((char*)sStruct,sizeof(saleStruct));
    salesFile.flush();
}

void Database::updateMember(int id) {
    int offset=8+sizeof(int)+id*(sizeof(customerStruct)+1)+1;
    customerStruct cStruct=members[id]->getStruct();
    membersFile.seekp(offset);
    membersFile.write((char*)&cStruct,sizeof(customerStruct));
    membersFile.flush();
}

Customer* Database::getMember(int id) {
    if (id>=(int)members.size()) {
        return NULL;
    } else {;
        return members[id];
    }
}

int Database::getMemberCount() {
    return members.size();
}<commit_msg>Just living in the database<commit_after>#include <iostream>
#include <cstdlib>
#include <cstring>
#include "database.hpp"
#include "transaction.hpp"
#include "customer.hpp"

using namespace std;

void Database::initFile(const char* filename, fstream& fs) {
    char magic[8]="CINEMAN";
    fs.open(filename,fstream::in);
    if(fs.fail()) {
        fs.close();
        fs.open(filename,fstream::out|fstream::binary);
        fs.write(magic,8);
        for(int i=0;i<4;i++) {fs.put(0);}
    }
    fs.close();
    fs.open(filename,fstream::in|fstream::out|fstream::binary);
    fs.seekg(0);
    char fmagic[8];
    fs.read(fmagic,8);
    if(strcmp(fmagic,magic)!=0) {
        cout << "Error: Invalid or corrupted database file!" << endl;
        exit(EXIT_FAILURE);
    }
}

Database::Database() { //Just living in the database, wow wow~
    initFile("members.db",this->membersFile);
    initFile("sales.db",this->salesFile);
    loadMembers();
    loadSales();
}

Database::~Database() {
    membersFile.close();
    salesFile.close();
}

void Database::loadMembers() {
    int memberCount;
    membersFile.seekg(8);
    membersFile.read((char*)&memberCount,sizeof(int));
    for(int i=0;i<memberCount;i++) {
        char memberType;
        customerStruct cStruct;
        membersFile.read(&memberType,1);
        membersFile.read((char*)&cStruct,sizeof(customerStruct));
        Customer *c;
        switch(memberType) {
            case 1:
                c=new MemberGold(i,&cStruct);
                break;
            case 2:
                c=new MemberPlatinum(i,&cStruct);
                break;
            default:
                cout << "Error reading database: Unknown member type at ID: " << i << endl;
                exit(EXIT_FAILURE);
                break;
        }
        members.push_back((Customer*)c);
    }
}

void Database::loadSales() {
    int salesCount;
    salesFile.seekg(8);
    salesFile.read((char*)&salesCount,sizeof(int));
    for(int i=0;i<salesCount;i++) {
        cout << i << endl;
        saleStruct* sStruct=new saleStruct;
        salesFile.read((char*)sStruct,sizeof(saleStruct));
        sales.push_back(sStruct);
    }
}

void Database::addMember(Customer* c) {
    int newID=members.size()+1;
    members.push_back(c);
    customerStruct cStruct=c->getStruct();
    char memberType=c->getType();
    membersFile.seekp(8);
    membersFile.write((char*)&newID,sizeof(int));
    membersFile.seekp(0,ios_base::end);
    membersFile.write(&memberType,1);
    membersFile.write((char*)&cStruct,sizeof(customerStruct));
    membersFile.flush();
}

void Database::addSale(saleStruct* sStruct) {
    int newID=sales.size()+1;
    sales.push_back(sStruct);
    salesFile.seekp(8);
    salesFile.write((char*)&newID,sizeof(int));
    salesFile.seekp(0,ios_base::end);
    salesFile.write((char*)sStruct,sizeof(saleStruct));
    salesFile.flush();
}

void Database::updateMember(int id) {
    int offset=8+sizeof(int)+id*(sizeof(customerStruct)+1)+1;
    customerStruct cStruct=members[id]->getStruct();
    membersFile.seekp(offset);
    membersFile.write((char*)&cStruct,sizeof(customerStruct));
    membersFile.flush();
}

Customer* Database::getMember(int id) {
    if (id>=(int)members.size()) {
        return NULL;
    } else {;
        return members[id];
    }
}

int Database::getMemberCount() {
    return members.size();
}
<|endoftext|>


<commit_before>#include <io/Socket.hpp>
#include <io/ServerSocket.hpp>
#include <io/StringWriter.hpp>
#include <test.h>

#include <unistd.h>
#include <cstdlib>
#include <sys/wait.h>
#include <io/Inet4Address.hpp>
#include <io/Inet6Address.hpp>
#include <io/UnixAddress.hpp>

#include <cstdlib>

using namespace io;
using namespace std;

int server(const SocketAddress& bind_addr) {

    try {
        StreamServerSocket* server_sock =
            StreamServerSocket::createAndBindListen(bind_addr);

        TEST_BOOL("createBindAndListen", server_sock != NULL);
        LOG("%s","Server socket opened\n");

        StreamSocket* sock = server_sock->accept();
        StringWriter writer;

        writer.stealBaseIO( (BaseIO*&)sock );
        writer.printf("Test%d", 0);

        return 0;
    } catch (CException& err) {
        LOG("Error running server: %s\n", err.getMessage());
        return 1;
    }
}

int client(const SocketAddress& connect) {
    StreamSocket* sock = new StreamSocket();

    int rc = 1;

    try {
        rc = sock->connect( connect );
    } catch (InetParseException& p) {
        LOG("Caught exception: %s\n", p.getMessage());
    }

    TEST_EQ_INT( "connect", rc, 0 );

    char test[4096];
    int size = sock->read( (byte*)test, 4096 - 1);
    TEST_BOOL( "read", size > 0 );
    test[size]=0;
    TEST_EQ( "strncmp", strncmp(test, "Test0", size), 0 ) ;

    delete sock;
    return 0;
}

int test_socket( const SocketAddress& addr ) {
    int rc;

    if( fork() == 0 ) {
        exit( server(addr) );
    } else {
        sleep(1);
        TEST_FN( client(addr) );
    }

    wait( & rc );
    TEST_EQ( "ServerExit", rc, 0 );

    return 0;
}

#define LOCALHOST 0x7f000001
int main( int argc, char** argv ) {
    (void) argc;
    (void) argv;
    int rc = 0;

    srand(time(NULL));
    uint16_t port = rand() % 50000 + 5000 ;
    uint16_t port6 = rand() % 50000 + 5000 ;

    Inet4Address iaddr(LOCALHOST, port);
    UnixAddress uaddr("/tmp/myunixsocket.sock");
    Inet6Address i6addr = Inet6Address::fromString("::1", port6);

    uaddr.unlink();

    LOG("Testing IPv4%s", "");
    TEST_FN( test_socket(iaddr) );
    LOG("Testing IPv6%s", "");
    TEST_FN( test_socket(i6addr) );
    LOG("Testing Unix%s", "");
    TEST_FN( test_socket(uaddr) );

    uaddr.unlink();

    return rc;
}
<commit_msg>modifications to sockets tests<commit_after>#include <io/Socket.hpp>
#include <io/ServerSocket.hpp>
#include <io/StringWriter.hpp>
#include <test.h>

#include <unistd.h>
#include <cstdlib>
#include <sys/wait.h>
#include <io/Inet4Address.hpp>
#include <io/Inet6Address.hpp>
#include <io/UnixAddress.hpp>

#include <cstdlib>

using namespace io;
using namespace std;

int server(const SocketAddress& bind_addr) {

    try {
        StreamServerSocket* server_sock =
            StreamServerSocket::createAndBindListen(bind_addr);

        TEST_BOOL("createBindAndListen", server_sock != NULL);
        LOG("%s","Server socket opened\n");

        StreamSocket* sock = server_sock->accept();
        StringWriter writer;

        LOG("%s","Connection accepted\n");
        byte *b = (byte*)"Test0";
        sock->write(b, sizeof("Test0"));

        return 0;
    } catch (CException& err) {
        LOG("Error running server: %s\n", err.getMessage());
        return 1;
    }
}

int client(const SocketAddress& connect) {
    StreamSocket* sock = new StreamSocket();

    int rc = 1;

    try {
        rc = sock->connect( connect );
    } catch (InetParseException& p) {
        LOG("Caught exception: %s\n", p.getMessage());
    }

    TEST_EQ_INT( "connect", rc, 0 );

    char test[4096];
    std::fill(test, test+4096, 0);
    int size = sock->read( (byte*)test, 4096 - 1);
    printf("size = %d\n", size);
    TEST_BOOL( "read", size >= 0 );
    test[size]=0;
    TEST_EQ( "strncmp", strncmp(test, "Test0", sizeof("Test0")), 0 ) ;

    delete sock;
    return 0;
}

int test_socket( const SocketAddress& addr ) {
    int rc;

    if( fork() == 0 ) {
        int rc = server(addr);
        if ( rc ) {
            LOG("Server Exit with bad code %s", "");
        }
        exit(rc);
    } else {
        sleep(1);
        TEST_FN( client(addr) );
    }

    wait( & rc );
    TEST_EQ( "ServerExit", rc, 0 );

    return 0;
}

#define LOCALHOST 0x7f000001
int main( int argc, char** argv ) {
    (void) argc;
    (void) argv;
    int rc = 0;

    srand(time(NULL));
    uint16_t port = rand() % 50000 + 5000 ;
    uint16_t port6 = rand() % 50000 + 5000 ;

    Inet4Address iaddr(LOCALHOST, port);
    UnixAddress uaddr("/tmp/myunixsocket.sock");
    Inet6Address i6addr = Inet6Address::fromString("::1", port6);

    uaddr.unlink();

    LOG("Testing IPv4%s", "");
    TEST_FN( test_socket(iaddr) );
    LOG("Testing IPv6%s", "");
    TEST_FN( test_socket(i6addr) );
    LOG("Testing Unix%s", "");
    TEST_FN( test_socket(uaddr) );

    uaddr.unlink();

    return rc;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <algorithm>
#define CAFFEX_IMPL 1
#include "caffex.h"

namespace caffex {

Caffex::Caffex(string const& model_dir, unsigned batch)
    : net(model_dir + "/caffe.model", TEST)
{
#ifdef CPU_ONLY
    Caffe::set_mode(Caffe::CPU);
#else
    BOOST_VERIFY(0);    // GPU is not supported here
#endif
    BOOST_VERIFY(batch >= 1);

    CHECK_EQ(net.num_inputs(), 1) << "Network should have exactly one input." << net.num_inputs();
    input_blob = net.input_blobs()[0];
    input_batch = batch;
    input_channels = input_blob->shape(1);

    CHECK(input_channels == 3 || input_channels == 1)
        << "Input layer should have 1 or 3 channels.";

    net.CopyTrainedLayersFrom(model_dir + "/caffe.params");
    // resize to required batch size
    int input_h = input_blob->shape(2);
    int input_w = input_blob->shape(3);
    fix_shape = ((input_h > 1) && (input_w > 1));
    if (!fix_shape) {
        BOOST_VERIFY(input_h == 1);
        BOOST_VERIFY(input_w == 1);
    }
    input_blob->Reshape(input_batch, input_channels, input_h, input_w); // placeholder, not used anyway
    net.Reshape();

    // set mean file
    means.push_back(0);
    string mean_file = model_dir + "/caffe.mean";
    std::ifstream test(mean_file.c_str());
    if (test) {
        means.clear();
        float mean;
        while (test >> mean) {
            means.push_back(mean);
        }
    }
    {
        string blobs_file = model_dir + "/blobs";
        std::ifstream is(blobs_file.c_str());
        string blob;
        CHECK(is) << "cannot open blobs file.";
        while (is >> blob) {
            shared_ptr<Blob<float>> b = net.blob_by_name(blob);
            output_blobs.push_back(b);
        }
    }
}

void Caffex::wrapInputLayer (std::vector<cv::Mat>* channels) {
    int input_height = input_blob->shape(2);
    int input_width = input_blob->shape(3);
    float *input_data = input_blob->mutable_cpu_data();
    for (int i = 0; i < input_batch; ++i) {
        for (int j = 0; j < input_channels; ++j) {
            cv::Mat m(input_height, input_width, CV_32FC1, input_data);
            channels->push_back(m);
            input_data += m.total();
        }
    }
}

void Caffex::preprocess(cv::Mat const &img, cv::Mat *channels) {
    if (img.total() == 0) {
        for (int i = 0; i < input_channels; ++i) {
            channels[i].setTo(cv::Scalar(0));
        }
        return;
    }
    /* Convert the input image to the input image format of the network. */
    cv::Mat sample;
    if (img.channels() == 3 && input_channels == 1)
    cv::cvtColor(img, sample, CV_BGR2GRAY);
    else if (img.channels() == 4 && input_channels == 1)
    cv::cvtColor(img, sample, CV_BGRA2GRAY);
    else if (img.channels() == 4 && input_channels == 3)
    cv::cvtColor(img, sample, CV_BGRA2BGR);
    else if (img.channels() == 1 && input_channels == 3)
    cv::cvtColor(img, sample, CV_GRAY2BGR);
    else
    sample = img;

    cv::Mat sample_resized;
    if (fix_shape) {
        cv::Size sz(input_blob->shape(3), input_blob->shape(2));
        if (sz == sample.size()) {
            sample_resized = sample;
        }
        else {
            cv::resize(sample, sample_resized, sz);
        }
    }
    else {
        sample_resized = sample;
    }

    cv::Mat sample_float;
    if ((sample_resized.type() == CV_32FC1) || (sample_resized.type() == CV_32FC3)) {
        sample_float = sample_resized;
    }
    else if (input_channels == 3)
    sample_resized.convertTo(sample_float, CV_32FC3);
    else
    sample_resized.convertTo(sample_float, CV_32FC1);

    cv::Mat sample_normalized;
    if (sample_float.depth() == 1) {
        sample_normalized = sample_float - cv::Scalar(means[0]);
    }
    else {
        sample_normalized = sample_float - cv::Scalar(means[0], means[1], means[2]);
    }

    /* This operation will write the separate BGR planes directly to the
   * input layer of the network because it is wrapped by the cv::Mat
   * objects in input_channels. */
    cv::split(sample_normalized, channels);
}

void Caffex::extractOutputValues (float *ptr, int output_dim, int n) {
    for (auto const &blob: output_blobs) {
      int blob_dim = blob->count() / input_batch;
      float const *from_begin = blob->cpu_data() + blob->offset(0);
      float *to_begin = ptr;
      for (int i = 0; i < n; ++i) {
          float const *from_end = from_begin + blob_dim;
          std::copy(from_begin, from_end, to_begin);
          from_begin = from_end;
          to_begin += output_dim;
      }
      ptr += blob_dim;
    }
}

void Caffex::checkReshape (cv::Mat const &image) {
    if (!fix_shape) {
        int input_height = input_blob->shape(2);
        int input_width = input_blob->shape(3);
        if ((input_width != image.cols)
                || (input_height != image.rows)) {
            input_blob->Reshape(input_batch, input_channels, image.rows, image.cols);
            net.Reshape();
        }
    }
}

int Caffex::dim () const {
    int v = 0;
    for (auto const &b: output_blobs) {
        v += b->count() / input_batch;
    }
    return v;
}

void Caffex::apply (const cv::Mat &image, vector<float> *ft) {
    checkReshape(image);
    int output_dim = dim(); // output dim changed after reshape

    vector<cv::Mat> channels;
    wrapInputLayer(&channels);
    preprocess(image, &channels);
    CHECK(reinterpret_cast<float*>(channels[0].data) == net.input_blobs()[0]->cpu_data())
        << "Input channels are not wrapping the input layer of the network.";
    net.ForwardPrefilled();
    ft->resize(output_dim);
    extractOutputValues(&ft->at(0), output_dim, 1);
}

void Caffex::apply(vector<cv::Mat> const &images, cv::Mat *ft) {
    CHECK(!images.empty()) << "must input >= 1 images";
    CHECK(images.size() <= input_batch) << "Too many input images.";
    if (!fix_shape) {
        for (unsigned i = 1; i < images.size(); ++i) {
            CHECK(images[i].size() == images[0].size()) << "all images must be the same size";
        }
    }
    checkReshape(images[0]);
    int output_dim = dim(); // output dim changed after reshape

    vector<cv::Mat> channels;
    wrapInputLayer(&channels);
    preprocess(images, &channels);
    CHECK(reinterpret_cast<float*>(channels[0].data) == net.input_blobs()[0]->cpu_data())
        << "Input channels are not wrapping the input layer of the network.";
    net.ForwardPrefilled();
    ft->create(images.size(), output_dim, CV_32FC1);
    extractOutputValues(ft->ptr<float>(0), output_dim, images.size());
}

}

<commit_msg>update<commit_after>#include <iostream>
#include <fstream>
#include <algorithm>
#define CAFFEX_IMPL 1
#include "caffex.h"

namespace caffex {

Caffex::Caffex(string const& model_dir, unsigned batch)
    : net(model_dir + "/caffe.model", TEST)
{
#ifdef CPU_ONLY
    Caffe::set_mode(Caffe::CPU);
#else
    BOOST_VERIFY(0);    // GPU is not supported here
#endif
    BOOST_VERIFY(batch >= 1);

    CHECK_EQ(net.num_inputs(), 1) << "Network should have exactly one input." << net.num_inputs();
    input_blob = net.input_blobs()[0];
    input_batch = batch;
    input_channels = input_blob->shape(1);

    CHECK(input_channels == 3 || input_channels == 1)
        << "Input layer should have 1 or 3 channels.";

    net.CopyTrainedLayersFrom(model_dir + "/caffe.params");
    // resize to required batch size
    int input_h = input_blob->shape(2);
    int input_w = input_blob->shape(3);
    fix_shape = ((input_h > 1) && (input_w > 1));
    if (!fix_shape) {
        BOOST_VERIFY(input_h == 1);
        BOOST_VERIFY(input_w == 1);
    }
    input_blob->Reshape(input_batch, input_channels, input_h, input_w); // placeholder, not used anyway
    net.Reshape();

    // set mean file
    means.push_back(0);
    means.push_back(0);
    means.push_back(0);
    string mean_file = model_dir + "/caffe.mean";
    std::ifstream test(mean_file.c_str());
    if (test) {
        means.clear();
        float mean;
        while (test >> mean) {
            means.push_back(mean);
        }
    }
    {
        string blobs_file = model_dir + "/blobs";
        std::ifstream is(blobs_file.c_str());
        string blob;
        CHECK(is) << "cannot open blobs file.";
        while (is >> blob) {
            shared_ptr<Blob<float>> b = net.blob_by_name(blob);
            output_blobs.push_back(b);
        }
    }
}

void Caffex::wrapInputLayer (std::vector<cv::Mat>* channels) {
    int input_height = input_blob->shape(2);
    int input_width = input_blob->shape(3);
    float *input_data = input_blob->mutable_cpu_data();
    for (int i = 0; i < input_batch; ++i) {
        for (int j = 0; j < input_channels; ++j) {
            cv::Mat m(input_height, input_width, CV_32FC1, input_data);
            channels->push_back(m);
            input_data += m.total();
        }
    }
}

void Caffex::preprocess(cv::Mat const &img, cv::Mat *channels) {
    if (img.total() == 0) {
        for (int i = 0; i < input_channels; ++i) {
            channels[i].setTo(cv::Scalar(0));
        }
        return;
    }
    /* Convert the input image to the input image format of the network. */
    cv::Mat sample;
    if (img.channels() == 3 && input_channels == 1)
    cv::cvtColor(img, sample, CV_BGR2GRAY);
    else if (img.channels() == 4 && input_channels == 1)
    cv::cvtColor(img, sample, CV_BGRA2GRAY);
    else if (img.channels() == 4 && input_channels == 3)
    cv::cvtColor(img, sample, CV_BGRA2BGR);
    else if (img.channels() == 1 && input_channels == 3)
    cv::cvtColor(img, sample, CV_GRAY2BGR);
    else
    sample = img;

    cv::Mat sample_resized;
    if (fix_shape) {
        cv::Size sz(input_blob->shape(3), input_blob->shape(2));
        if (sz == sample.size()) {
            sample_resized = sample;
        }
        else {
            cv::resize(sample, sample_resized, sz);
        }
    }
    else {
        sample_resized = sample;
    }

    cv::Mat sample_float;
    if ((sample_resized.type() == CV_32FC1) || (sample_resized.type() == CV_32FC3)) {
        sample_float = sample_resized;
    }
    else if (input_channels == 3)
    sample_resized.convertTo(sample_float, CV_32FC3);
    else
    sample_resized.convertTo(sample_float, CV_32FC1);

    cv::Mat sample_normalized;
    if (sample_float.depth() == 1) {
        sample_normalized = sample_float - cv::Scalar(means[0]);
    }
    else {
        CHECK(means.size() >= 3);
        sample_normalized = sample_float - cv::Scalar(means[0], means[1], means[2]);
    }

    /* This operation will write the separate BGR planes directly to the
   * input layer of the network because it is wrapped by the cv::Mat
   * objects in input_channels. */
    cv::split(sample_normalized, channels);
}

void Caffex::extractOutputValues (float *ptr, int output_dim, int n) {
    for (auto const &blob: output_blobs) {
      int blob_dim = blob->count() / input_batch;
      float const *from_begin = blob->cpu_data() + blob->offset(0);
      float *to_begin = ptr;
      for (int i = 0; i < n; ++i) {
          float const *from_end = from_begin + blob_dim;
          std::copy(from_begin, from_end, to_begin);
          from_begin = from_end;
          to_begin += output_dim;
      }
      ptr += blob_dim;
    }
}

void Caffex::checkReshape (cv::Mat const &image) {
    if (!fix_shape) {
        int input_height = input_blob->shape(2);
        int input_width = input_blob->shape(3);
        if ((input_width != image.cols)
                || (input_height != image.rows)) {
            input_blob->Reshape(input_batch, input_channels, image.rows, image.cols);
            net.Reshape();
        }
    }
}

int Caffex::dim () const {
    int v = 0;
    for (auto const &b: output_blobs) {
        v += b->count() / input_batch;
    }
    return v;
}

void Caffex::apply (const cv::Mat &image, vector<float> *ft) {
    checkReshape(image);
    int output_dim = dim(); // output dim changed after reshape

    vector<cv::Mat> channels;
    wrapInputLayer(&channels);
    preprocess(image, &channels);
    CHECK(reinterpret_cast<float*>(channels[0].data) == net.input_blobs()[0]->cpu_data())
        << "Input channels are not wrapping the input layer of the network.";
    net.ForwardPrefilled();
    ft->resize(output_dim);
    extractOutputValues(&ft->at(0), output_dim, 1);
}

void Caffex::apply(vector<cv::Mat> const &images, cv::Mat *ft) {
    CHECK(!images.empty()) << "must input >= 1 images";
    CHECK(images.size() <= input_batch) << "Too many input images.";
    if (!fix_shape) {
        for (unsigned i = 1; i < images.size(); ++i) {
            CHECK(images[i].size() == images[0].size()) << "all images must be the same size";
        }
    }
    checkReshape(images[0]);
    int output_dim = dim(); // output dim changed after reshape

    vector<cv::Mat> channels;
    wrapInputLayer(&channels);
    preprocess(images, &channels);
    CHECK(reinterpret_cast<float*>(channels[0].data) == net.input_blobs()[0]->cpu_data())
        << "Input channels are not wrapping the input layer of the network.";
    net.ForwardPrefilled();
    ft->create(images.size(), output_dim, CV_32FC1);
    extractOutputValues(ft->ptr<float>(0), output_dim, images.size());
}

}

<|endoftext|>


<commit_before>//===- DAGISelEmitter.cpp - Generate an instruction selector --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend emits a DAG instruction selector.
//
//===----------------------------------------------------------------------===//

#include "DAGISelEmitter.h"
#include "DAGISelMatcher.h"
#include "Record.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// DAGISelEmitter Helper methods
//

/// getResultPatternCost - Compute the number of instructions for this pattern.
/// This is a temporary hack.  We should really include the instruction
/// latencies in this calculation.
static unsigned getResultPatternCost(TreePatternNode *P,
                                     CodeGenDAGPatterns &CGP) {
  if (P->isLeaf()) return 0;

  unsigned Cost = 0;
  Record *Op = P->getOperator();
  if (Op->isSubClassOf("Instruction")) {
    Cost++;
    CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
    if (II.usesCustomInserter)
      Cost += 10;
  }
  for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
    Cost += getResultPatternCost(P->getChild(i), CGP);
  return Cost;
}

/// getResultPatternCodeSize - Compute the code size of instructions for this
/// pattern.
static unsigned getResultPatternSize(TreePatternNode *P,
                                     CodeGenDAGPatterns &CGP) {
  if (P->isLeaf()) return 0;

  unsigned Cost = 0;
  Record *Op = P->getOperator();
  if (Op->isSubClassOf("Instruction")) {
    Cost += Op->getValueAsInt("CodeSize");
  }
  for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
    Cost += getResultPatternSize(P->getChild(i), CGP);
  return Cost;
}

//===----------------------------------------------------------------------===//
// Predicate emitter implementation.
//

void DAGISelEmitter::EmitPredicateFunctions(raw_ostream &OS) {
  OS << "\n// Predicate functions.\n";

  // Walk the pattern fragments, adding them to a map, which sorts them by
  // name.
  typedef std::map<std::string, std::pair<Record*, TreePattern*> > PFsByNameTy;
  PFsByNameTy PFsByName;

  for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end();
       I != E; ++I)
    PFsByName.insert(std::make_pair(I->first->getName(), *I));

  for (PFsByNameTy::iterator I = PFsByName.begin(), E = PFsByName.end();
       I != E; ++I) {
    Record *PatFragRecord = I->second.first;// Record that derives from PatFrag.
    TreePattern *P = I->second.second;

    // If there is a code init for this fragment, emit the predicate code.
    std::string Code = PatFragRecord->getValueAsCode("Predicate");
    if (Code.empty()) continue;

    if (P->getOnlyTree()->isLeaf())
      OS << "inline bool Predicate_" << PatFragRecord->getName()
      << "(SDNode *N) const {\n";
    else {
      std::string ClassName =
        CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
      const char *C2 = ClassName == "SDNode" ? "N" : "inN";

      OS << "inline bool Predicate_" << PatFragRecord->getName()
         << "(SDNode *" << C2 << ") const {\n";
      if (ClassName != "SDNode")
        OS << "  " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
    }
    OS << Code << "\n}\n";
  }

  OS << "\n\n";
}

namespace {
// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
// In particular, we want to match maximal patterns first and lowest cost within
// a particular complexity first.
struct PatternSortingPredicate {
  PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
  CodeGenDAGPatterns &CGP;

  bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) {
    // Otherwise, if the patterns might both match, sort based on complexity,
    // which means that we prefer to match patterns that cover more nodes in the
    // input over nodes that cover fewer.
    unsigned LHSSize = LHS->getPatternComplexity(CGP);
    unsigned RHSSize = RHS->getPatternComplexity(CGP);
    if (LHSSize > RHSSize) return true;   // LHS -> bigger -> less cost
    if (LHSSize < RHSSize) return false;

    // If the patterns have equal complexity, compare generated instruction cost
    unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP);
    unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP);
    if (LHSCost < RHSCost) return true;
    if (LHSCost > RHSCost) return false;

    unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP);
    unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP);
    if (LHSPatSize < RHSPatSize) return true;
    if (LHSPatSize > RHSPatSize) return false;

    // Sort based on the UID of the pattern, giving us a deterministic ordering
    // if all other sorting conditions fail.
    assert(LHS == RHS || LHS->ID != RHS->ID);
    return LHS->ID < RHS->ID;
  }
};
}

void DAGISelEmitter::run(raw_ostream &OS) {
  EmitSourceFileHeader("DAG Instruction Selector for the " +
                       CGP.getTargetInfo().getName() + " target", OS);

  OS << "// *** NOTE: This file is #included into the middle of the target\n"
     << "// *** instruction selector class.  These functions are really "
     << "methods.\n\n";

  DEBUG(errs() << "\n\nALL PATTERNS TO MATCH:\n\n";
        for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
             E = CGP.ptm_end(); I != E; ++I) {
          errs() << "PATTERN: ";   I->getSrcPattern()->dump();
          errs() << "\nRESULT:  "; I->getDstPattern()->dump();
          errs() << "\n";
        });

  // FIXME: These are being used by hand written code, gross.
  EmitPredicateFunctions(OS);

  // Add all the patterns to a temporary list so we can sort them.
  std::vector<const PatternToMatch*> Patterns;
  for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
       I != E; ++I)
    Patterns.push_back(&*I);

  // We want to process the matches in order of minimal cost.  Sort the patterns
  // so the least cost one is at the start.
  std::stable_sort(Patterns.begin(), Patterns.end(),
                   PatternSortingPredicate(CGP));

  // Convert each variant of each pattern into a Matcher.
  std::vector<Matcher*> PatternMatchers;
  for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
    for (unsigned Variant = 0; ; ++Variant) {
      if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP))
        PatternMatchers.push_back(M);
      else
        break;
    }
  }

  Matcher *TheMatcher = new ScopeMatcher(&PatternMatchers[0],
                                         PatternMatchers.size());

  TheMatcher = OptimizeMatcher(TheMatcher, CGP);
  //Matcher->dump();
  EmitMatcherTable(TheMatcher, CGP, OS);
  delete TheMatcher;
}
<commit_msg>Switch pattern sorting predicate from stable sort -> sort, it doesn't need to be stable because the patterns are fully ordered.<commit_after>//===- DAGISelEmitter.cpp - Generate an instruction selector --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend emits a DAG instruction selector.
//
//===----------------------------------------------------------------------===//

#include "DAGISelEmitter.h"
#include "DAGISelMatcher.h"
#include "Record.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// DAGISelEmitter Helper methods
//

/// getResultPatternCost - Compute the number of instructions for this pattern.
/// This is a temporary hack.  We should really include the instruction
/// latencies in this calculation.
static unsigned getResultPatternCost(TreePatternNode *P,
                                     CodeGenDAGPatterns &CGP) {
  if (P->isLeaf()) return 0;

  unsigned Cost = 0;
  Record *Op = P->getOperator();
  if (Op->isSubClassOf("Instruction")) {
    Cost++;
    CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
    if (II.usesCustomInserter)
      Cost += 10;
  }
  for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
    Cost += getResultPatternCost(P->getChild(i), CGP);
  return Cost;
}

/// getResultPatternCodeSize - Compute the code size of instructions for this
/// pattern.
static unsigned getResultPatternSize(TreePatternNode *P,
                                     CodeGenDAGPatterns &CGP) {
  if (P->isLeaf()) return 0;

  unsigned Cost = 0;
  Record *Op = P->getOperator();
  if (Op->isSubClassOf("Instruction")) {
    Cost += Op->getValueAsInt("CodeSize");
  }
  for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
    Cost += getResultPatternSize(P->getChild(i), CGP);
  return Cost;
}

//===----------------------------------------------------------------------===//
// Predicate emitter implementation.
//

void DAGISelEmitter::EmitPredicateFunctions(raw_ostream &OS) {
  OS << "\n// Predicate functions.\n";

  // Walk the pattern fragments, adding them to a map, which sorts them by
  // name.
  typedef std::map<std::string, std::pair<Record*, TreePattern*> > PFsByNameTy;
  PFsByNameTy PFsByName;

  for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end();
       I != E; ++I)
    PFsByName.insert(std::make_pair(I->first->getName(), *I));

  for (PFsByNameTy::iterator I = PFsByName.begin(), E = PFsByName.end();
       I != E; ++I) {
    Record *PatFragRecord = I->second.first;// Record that derives from PatFrag.
    TreePattern *P = I->second.second;

    // If there is a code init for this fragment, emit the predicate code.
    std::string Code = PatFragRecord->getValueAsCode("Predicate");
    if (Code.empty()) continue;

    if (P->getOnlyTree()->isLeaf())
      OS << "inline bool Predicate_" << PatFragRecord->getName()
      << "(SDNode *N) const {\n";
    else {
      std::string ClassName =
        CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
      const char *C2 = ClassName == "SDNode" ? "N" : "inN";

      OS << "inline bool Predicate_" << PatFragRecord->getName()
         << "(SDNode *" << C2 << ") const {\n";
      if (ClassName != "SDNode")
        OS << "  " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
    }
    OS << Code << "\n}\n";
  }

  OS << "\n\n";
}

namespace {
// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
// In particular, we want to match maximal patterns first and lowest cost within
// a particular complexity first.
struct PatternSortingPredicate {
  PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
  CodeGenDAGPatterns &CGP;

  bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) {
    const TreePatternNode *LHSSrc = LHS->getSrcPattern();
    const TreePatternNode *RHSSrc = RHS->getSrcPattern();

    if (LHSSrc->getNumTypes() != 0 && RHSSrc->getNumTypes() != 0 &&
        LHSSrc->getType(0) != RHSSrc->getType(0)) {
      MVT::SimpleValueType V1 = LHSSrc->getType(0), V2 = RHSSrc->getType(0);
      if (MVT(V1).isVector() != MVT(V2).isVector())
        return MVT(V2).isVector();

      if (MVT(V1).isFloatingPoint() != MVT(V2).isFloatingPoint())
        return MVT(V2).isFloatingPoint();
    }

    // Otherwise, if the patterns might both match, sort based on complexity,
    // which means that we prefer to match patterns that cover more nodes in the
    // input over nodes that cover fewer.
    unsigned LHSSize = LHS->getPatternComplexity(CGP);
    unsigned RHSSize = RHS->getPatternComplexity(CGP);
    if (LHSSize > RHSSize) return true;   // LHS -> bigger -> less cost
    if (LHSSize < RHSSize) return false;

    // If the patterns have equal complexity, compare generated instruction cost
    unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP);
    unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP);
    if (LHSCost < RHSCost) return true;
    if (LHSCost > RHSCost) return false;

    unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP);
    unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP);
    if (LHSPatSize < RHSPatSize) return true;
    if (LHSPatSize > RHSPatSize) return false;

    // Sort based on the UID of the pattern, giving us a deterministic ordering
    // if all other sorting conditions fail.
    assert(LHS == RHS || LHS->ID != RHS->ID);
    return LHS->ID < RHS->ID;
  }
};
}

void DAGISelEmitter::run(raw_ostream &OS) {
  EmitSourceFileHeader("DAG Instruction Selector for the " +
                       CGP.getTargetInfo().getName() + " target", OS);

  OS << "// *** NOTE: This file is #included into the middle of the target\n"
     << "// *** instruction selector class.  These functions are really "
     << "methods.\n\n";

  DEBUG(errs() << "\n\nALL PATTERNS TO MATCH:\n\n";
        for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
             E = CGP.ptm_end(); I != E; ++I) {
          errs() << "PATTERN: ";   I->getSrcPattern()->dump();
          errs() << "\nRESULT:  "; I->getDstPattern()->dump();
          errs() << "\n";
        });

  // FIXME: These are being used by hand written code, gross.
  EmitPredicateFunctions(OS);

  // Add all the patterns to a temporary list so we can sort them.
  std::vector<const PatternToMatch*> Patterns;
  for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
       I != E; ++I)
    Patterns.push_back(&*I);

  // We want to process the matches in order of minimal cost.  Sort the patterns
  // so the least cost one is at the start.
  std::sort(Patterns.begin(), Patterns.end(), PatternSortingPredicate(CGP));

  // Convert each variant of each pattern into a Matcher.
  std::vector<Matcher*> PatternMatchers;
  for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
    for (unsigned Variant = 0; ; ++Variant) {
      if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP))
        PatternMatchers.push_back(M);
      else
        break;
    }
  }

  Matcher *TheMatcher = new ScopeMatcher(&PatternMatchers[0],
                                         PatternMatchers.size());

  TheMatcher = OptimizeMatcher(TheMatcher, CGP);
  //Matcher->dump();
  EmitMatcherTable(TheMatcher, CGP, OS);
  delete TheMatcher;
}
<|endoftext|>