<commit_before>/** \file    MediaTypeUtil.cc
 *  \brief   Implementation of Media Type utility functions.
 *  \author  Dr. Gordon W. Paynter
 *  \author  Dr. Johannes Ruscheinski
 */

/*
 *  Copyright 2004-2008 Project iVia.
 *  Copyright 2004-2008 The Regents of The University of California.
 *  Copyright 2016 Universitätsbibliothek Tübingen.
 *
 *  This file is part of the libiViaCore package.
 *
 *  The libiViaCore package is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License as published
 *  by the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  libiViaCore 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 libiViaCore; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "MediaTypeUtil.h"
#include <stdexcept>
#include <cctype>
#include <alloca.h>
#include <magic.h>
#include "File.h"
#include "HttpHeader.h"
#include "PerlCompatRegExp.h"
#include "StringUtil.h"
#include "Url.h"
#include "util.h"
#include "WebUtil.h"
#include "XMLParser.h"
#include <iostream>

namespace MediaTypeUtil {

std::string GetHtmlMediaType(const std::string &document) {
    static const PerlCompatRegExp doctype_regexp("^\\s*<(?:!DOCTYPE\\s+HTML\\s+PUBLIC\\s+\"-//W3C//DTD\\s+){0,1}(X?HTML)|<html>",
                                                 PerlCompatRegExp::OPTIMIZE_FOR_MULTIPLE_USE, PCRE_CASELESS);

    // If we have a match we have either HTML or XHTML...
    std::string matched_substring;
    if (doctype_regexp.match(document) and doctype_regexp.getMatchedSubstring(1, &matched_substring))
        return matched_substring.length() == 4 ? "text/html" : "text/xhtml";

    // ...otherwise we have no idea what we have:
    return "";
}

static std::string LZ4_MAGIC("\000\042\115\030");

// GetMediaType -- Get the media type of a document.
//
std::string GetMediaType(const std::string &document, const bool auto_simplify) {
    if (document.empty())
        return "";

    // 1. See if we have (X)HTML:
    std::string media_type(GetHtmlMediaType(document));
    if (not media_type.empty())
        return media_type;

    // 2. Check for LZ4 compression:
    if (document.substr(0, 4) == LZ4_MAGIC)
        return "application/lz4";

    // 3. Next try libmagic:
    const magic_t cookie = ::magic_open(MAGIC_MIME);
    if (unlikely(cookie == nullptr))
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: could not open libmagic!");

    // Load the default "magic" definitions file:
    if (unlikely(::magic_load(cookie, nullptr /* use default magic file */) != 0)) {
        ::magic_close(cookie);
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: could not load libmagic ("
                                 + std::string(::magic_error(cookie)) + ").");
    }

    // Use magic to get the mime type of the buffer:
    const char *magic_mime_type = ::magic_buffer(cookie, document.c_str(), document.length());
    if (unlikely(magic_mime_type == nullptr)) {
        ::magic_close(cookie);
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: error in libmagic ("
                                 + std::string(::magic_error(cookie)) + ").");
    }

    // Attempt to remove possible leading junk (no idea why libmagic behaves in this manner every now and then):
    if (std::strncmp(magic_mime_type, "\\012- ", 6) == 0)
        magic_mime_type += 6;

    // Close the library:
    media_type = magic_mime_type;
    ::magic_close(cookie);

    // 4. If the libmagic could not determine the document's MIME type, test for XML:
    if (media_type.empty() and document.size() > 5)
        return std::strncmp(document.c_str(), "<?xml", 5) == 0 ? "text/xml" : "";

    if (auto_simplify)
        SimplifyMediaType(&media_type);

    return media_type;
}

std::string GetMediaType(const std::string &document, std::string * const subtype, const bool auto_simplify) {
    std::string media_type(GetMediaType(document, auto_simplify));
    // also include "text/html" which is reported by libmagic if xml prolog is missing
    if (media_type == "text/xml" or (media_type == "text/html" and not (GetHtmlMediaType(document) == "text/html"))) {
        XMLParser parser(document, XMLParser::XML_STRING);
        XMLParser::XMLPart part;
        if (parser.skipTo(XMLParser::XMLPart::OPENING_TAG, "", &part)) {
            const auto xmlns(part.attributes_.find("xmlns"));
            if (part.data_ == "TEI" and xmlns != part.attributes_.end() and xmlns->second == "http://www.tei-c.org/ns/1.0") {
                media_type = "text/xml";
                *subtype = "tei";
            }
        }
    }

    return media_type;
}

std::string GetFileMediaType(const std::string &filename, const bool auto_simplify) {
    const magic_t cookie(::magic_open(MAGIC_MIME | MAGIC_SYMLINK));
    if (unlikely(cookie == nullptr))
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: could not open libmagic!");

    // Load the default "magic" definitions file:
    if (unlikely(::magic_load(cookie, nullptr /* use default magic file */) != 0)) {
        ::magic_close(cookie);
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: could not load libmagic ("
                                 + std::string(::magic_error(cookie)) + ").");
    }

    // Use magic to get the mime type of the buffer:
    const char *magic_mime_type(::magic_file(cookie, filename.c_str()));
    if (unlikely(magic_mime_type == nullptr)) {
        ::magic_close(cookie);
        throw std::runtime_error("in MediaTypeUtil::GetFileMediaType: error in libmagic ("
                                 + std::string(::magic_error(cookie)) + ").");
    }

    // Attempt to remove possible leading junk (no idea why libmagic behaves in this manner every now and then):
    if (std::strncmp(magic_mime_type, "\\012- ", 6) == 0)
        magic_mime_type += 6;

    // Close the library:
    std::string media_type(magic_mime_type);
    ::magic_close(cookie);

    if (auto_simplify)
        SimplifyMediaType(&media_type);

    if (StringUtil::StartsWith(media_type, "application/octet-stream")) {
        File input(filename, "r");
        if (unlikely(input.anErrorOccurred()))
            logger->error("in MediaTypeUtil::GetFileMediaType: failed to open \"" + filename + "\" for reading!");
        char * const buf(reinterpret_cast<char *>(::alloca(LZ4_MAGIC.size())));
        if ((input.read(buf, sizeof(buf)) == sizeof(buf)) and std::strncmp(LZ4_MAGIC.c_str(), buf, LZ4_MAGIC.size()) == 0)
            return "application/lz4";
    }

    return media_type;
}

// GetMediaType -- get the media type of a Web page.
//
std::string GetMediaType(const std::string &page_header, const std::string &page_body, const bool auto_simplify) {
    // First, attempt to find the media type in the header:
    HttpHeader http_header(page_header);
    if (http_header.isValid()) {
        std::string media_type(http_header.getMediaType());
        if (not media_type.empty()) {
            StringUtil::ASCIIToLower(&media_type);
            if (auto_simplify)
                SimplifyMediaType(&media_type);
            return media_type;
        }
    }

    // Otherwise, check the content:
    return GetMediaType(page_body, auto_simplify);
}

// GetMediaType -- Get the MediaType of the page.  Returns true if "media_type" is known and set.
//
bool GetMediaType(const Url &url, const HttpHeader &http_header, const std::string &page_content,
                  std::string * const media_type, const bool auto_simplify)
{
    // First, attempt to find the media type in the header:
    if (http_header.isValid()) {
        *media_type = http_header.getMediaType();
        if (not media_type->empty()) {
            if (auto_simplify)
                SimplifyMediaType(media_type);
            return true;
        }
    }

    // Second, attempt to use the "magic" library (libmagic) to analyse the page:
    *media_type = MediaTypeUtil::GetMediaType(page_content);
    if (not media_type->empty()) {
        if (auto_simplify)
            SimplifyMediaType(media_type);
        return true;
    }

    // Third, guess based on URL:
    *media_type = WebUtil::GuessMediaType(url);
    if (not media_type->empty() and auto_simplify)
        SimplifyMediaType(media_type);
    return not media_type->empty();
}

std::string GetMediaType(const HttpHeader &http_header, const std::string &page_body, const bool auto_simplify) {
    std::string media_type;

    // First, attempt to find the media type in the header:
    if (http_header.isValid()) {
        media_type = http_header.getMediaType();
        if (not media_type.empty()) {
            StringUtil::ASCIIToLower(&media_type);
            if (auto_simplify)
                SimplifyMediaType(&media_type);
            return media_type;
        }
    }

    // Second, attempt to use the "magic" library (libmagic) to analyse the page:
    media_type = MediaTypeUtil::GetMediaType(page_body, auto_simplify);

    return media_type;
}

bool GetMediaType(const std::string &url, const HttpHeader &http_header, const std::string &page_content,
                  std::string * const media_type, const bool auto_simplify)
{
    return GetMediaType(Url(url), http_header, page_content, media_type, auto_simplify);
}

bool SimplifyMediaType(std::string * const media_type) {
    if (media_type->empty())
        return false;

    // This is the format of the Content-Type field for Web pages:
    //  media-type     = type "/" subtype *( ";" parameter )
    //  type           = token
    //      subtype        = token
    // See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7

    const std::string initial_media_type(*media_type);

    // Search for a semicolon and delete any 'parameter' parts:
    const std::string::size_type semicolon_pos(media_type->find(';'));
    if (semicolon_pos != std::string::npos)
        media_type->resize(semicolon_pos);
    else { // Try a space instead of a semicolon.
        const std::string::size_type space_pos(media_type->find(' '));
        if (space_pos != std::string::npos)
            media_type->resize(space_pos);
    }

    StringUtil::TrimWhite(media_type);

    // Return if "media_type" has changed:
    return initial_media_type != *media_type;
}

} // namespace MediaTypeUtil
<commit_msg>Remove debug include<commit_after>/** \file    MediaTypeUtil.cc
 *  \brief   Implementation of Media Type utility functions.
 *  \author  Dr. Gordon W. Paynter
 *  \author  Dr. Johannes Ruscheinski
 */

/*
 *  Copyright 2004-2008 Project iVia.
 *  Copyright 2004-2008 The Regents of The University of California.
 *  Copyright 2016 Universitätsbibliothek Tübingen.
 *
 *  This file is part of the libiViaCore package.
 *
 *  The libiViaCore package is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License as published
 *  by the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  libiViaCore 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 libiViaCore; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "MediaTypeUtil.h"
#include <stdexcept>
#include <cctype>
#include <alloca.h>
#include <magic.h>
#include "File.h"
#include "HttpHeader.h"
#include "PerlCompatRegExp.h"
#include "StringUtil.h"
#include "Url.h"
#include "util.h"
#include "WebUtil.h"
#include "XMLParser.h"

namespace MediaTypeUtil {

std::string GetHtmlMediaType(const std::string &document) {
    static const PerlCompatRegExp doctype_regexp("^\\s*<(?:!DOCTYPE\\s+HTML\\s+PUBLIC\\s+\"-//W3C//DTD\\s+){0,1}(X?HTML)|<html>",
                                                 PerlCompatRegExp::OPTIMIZE_FOR_MULTIPLE_USE, PCRE_CASELESS);

    // If we have a match we have either HTML or XHTML...
    std::string matched_substring;
    if (doctype_regexp.match(document) and doctype_regexp.getMatchedSubstring(1, &matched_substring))
        return matched_substring.length() == 4 ? "text/html" : "text/xhtml";

    // ...otherwise we have no idea what we have:
    return "";
}

static std::string LZ4_MAGIC("\000\042\115\030");

// GetMediaType -- Get the media type of a document.
//
std::string GetMediaType(const std::string &document, const bool auto_simplify) {
    if (document.empty())
        return "";

    // 1. See if we have (X)HTML:
    std::string media_type(GetHtmlMediaType(document));
    if (not media_type.empty())
        return media_type;

    // 2. Check for LZ4 compression:
    if (document.substr(0, 4) == LZ4_MAGIC)
        return "application/lz4";

    // 3. Next try libmagic:
    const magic_t cookie = ::magic_open(MAGIC_MIME);
    if (unlikely(cookie == nullptr))
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: could not open libmagic!");

    // Load the default "magic" definitions file:
    if (unlikely(::magic_load(cookie, nullptr /* use default magic file */) != 0)) {
        ::magic_close(cookie);
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: could not load libmagic ("
                                 + std::string(::magic_error(cookie)) + ").");
    }

    // Use magic to get the mime type of the buffer:
    const char *magic_mime_type = ::magic_buffer(cookie, document.c_str(), document.length());
    if (unlikely(magic_mime_type == nullptr)) {
        ::magic_close(cookie);
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: error in libmagic ("
                                 + std::string(::magic_error(cookie)) + ").");
    }

    // Attempt to remove possible leading junk (no idea why libmagic behaves in this manner every now and then):
    if (std::strncmp(magic_mime_type, "\\012- ", 6) == 0)
        magic_mime_type += 6;

    // Close the library:
    media_type = magic_mime_type;
    ::magic_close(cookie);

    // 4. If the libmagic could not determine the document's MIME type, test for XML:
    if (media_type.empty() and document.size() > 5)
        return std::strncmp(document.c_str(), "<?xml", 5) == 0 ? "text/xml" : "";

    if (auto_simplify)
        SimplifyMediaType(&media_type);

    return media_type;
}

std::string GetMediaType(const std::string &document, std::string * const subtype, const bool auto_simplify) {
    std::string media_type(GetMediaType(document, auto_simplify));
    // also include "text/html" which is reported by libmagic if xml prolog is missing
    if (media_type == "text/xml" or (media_type == "text/html" and not (GetHtmlMediaType(document) == "text/html"))) {
        XMLParser parser(document, XMLParser::XML_STRING);
        XMLParser::XMLPart part;
        if (parser.skipTo(XMLParser::XMLPart::OPENING_TAG, "", &part)) {
            const auto xmlns(part.attributes_.find("xmlns"));
            if (part.data_ == "TEI" and xmlns != part.attributes_.end() and xmlns->second == "http://www.tei-c.org/ns/1.0") {
                media_type = "text/xml";
                *subtype = "tei";
            }
        }
    }

    return media_type;
}

std::string GetFileMediaType(const std::string &filename, const bool auto_simplify) {
    const magic_t cookie(::magic_open(MAGIC_MIME | MAGIC_SYMLINK));
    if (unlikely(cookie == nullptr))
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: could not open libmagic!");

    // Load the default "magic" definitions file:
    if (unlikely(::magic_load(cookie, nullptr /* use default magic file */) != 0)) {
        ::magic_close(cookie);
        throw std::runtime_error("in MediaTypeUtil::GetMediaType: could not load libmagic ("
                                 + std::string(::magic_error(cookie)) + ").");
    }

    // Use magic to get the mime type of the buffer:
    const char *magic_mime_type(::magic_file(cookie, filename.c_str()));
    if (unlikely(magic_mime_type == nullptr)) {
        ::magic_close(cookie);
        throw std::runtime_error("in MediaTypeUtil::GetFileMediaType: error in libmagic ("
                                 + std::string(::magic_error(cookie)) + ").");
    }

    // Attempt to remove possible leading junk (no idea why libmagic behaves in this manner every now and then):
    if (std::strncmp(magic_mime_type, "\\012- ", 6) == 0)
        magic_mime_type += 6;

    // Close the library:
    std::string media_type(magic_mime_type);
    ::magic_close(cookie);

    if (auto_simplify)
        SimplifyMediaType(&media_type);

    if (StringUtil::StartsWith(media_type, "application/octet-stream")) {
        File input(filename, "r");
        if (unlikely(input.anErrorOccurred()))
            logger->error("in MediaTypeUtil::GetFileMediaType: failed to open \"" + filename + "\" for reading!");
        char * const buf(reinterpret_cast<char *>(::alloca(LZ4_MAGIC.size())));
        if ((input.read(buf, sizeof(buf)) == sizeof(buf)) and std::strncmp(LZ4_MAGIC.c_str(), buf, LZ4_MAGIC.size()) == 0)
            return "application/lz4";
    }

    return media_type;
}

// GetMediaType -- get the media type of a Web page.
//
std::string GetMediaType(const std::string &page_header, const std::string &page_body, const bool auto_simplify) {
    // First, attempt to find the media type in the header:
    HttpHeader http_header(page_header);
    if (http_header.isValid()) {
        std::string media_type(http_header.getMediaType());
        if (not media_type.empty()) {
            StringUtil::ASCIIToLower(&media_type);
            if (auto_simplify)
                SimplifyMediaType(&media_type);
            return media_type;
        }
    }

    // Otherwise, check the content:
    return GetMediaType(page_body, auto_simplify);
}

// GetMediaType -- Get the MediaType of the page.  Returns true if "media_type" is known and set.
//
bool GetMediaType(const Url &url, const HttpHeader &http_header, const std::string &page_content,
                  std::string * const media_type, const bool auto_simplify)
{
    // First, attempt to find the media type in the header:
    if (http_header.isValid()) {
        *media_type = http_header.getMediaType();
        if (not media_type->empty()) {
            if (auto_simplify)
                SimplifyMediaType(media_type);
            return true;
        }
    }

    // Second, attempt to use the "magic" library (libmagic) to analyse the page:
    *media_type = MediaTypeUtil::GetMediaType(page_content);
    if (not media_type->empty()) {
        if (auto_simplify)
            SimplifyMediaType(media_type);
        return true;
    }

    // Third, guess based on URL:
    *media_type = WebUtil::GuessMediaType(url);
    if (not media_type->empty() and auto_simplify)
        SimplifyMediaType(media_type);
    return not media_type->empty();
}

std::string GetMediaType(const HttpHeader &http_header, const std::string &page_body, const bool auto_simplify) {
    std::string media_type;

    // First, attempt to find the media type in the header:
    if (http_header.isValid()) {
        media_type = http_header.getMediaType();
        if (not media_type.empty()) {
            StringUtil::ASCIIToLower(&media_type);
            if (auto_simplify)
                SimplifyMediaType(&media_type);
            return media_type;
        }
    }

    // Second, attempt to use the "magic" library (libmagic) to analyse the page:
    media_type = MediaTypeUtil::GetMediaType(page_body, auto_simplify);

    return media_type;
}

bool GetMediaType(const std::string &url, const HttpHeader &http_header, const std::string &page_content,
                  std::string * const media_type, const bool auto_simplify)
{
    return GetMediaType(Url(url), http_header, page_content, media_type, auto_simplify);
}

bool SimplifyMediaType(std::string * const media_type) {
    if (media_type->empty())
        return false;

    // This is the format of the Content-Type field for Web pages:
    //  media-type     = type "/" subtype *( ";" parameter )
    //  type           = token
    //      subtype        = token
    // See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7

    const std::string initial_media_type(*media_type);

    // Search for a semicolon and delete any 'parameter' parts:
    const std::string::size_type semicolon_pos(media_type->find(';'));
    if (semicolon_pos != std::string::npos)
        media_type->resize(semicolon_pos);
    else { // Try a space instead of a semicolon.
        const std::string::size_type space_pos(media_type->find(' '));
        if (space_pos != std::string::npos)
            media_type->resize(space_pos);
    }

    StringUtil::TrimWhite(media_type);

    // Return if "media_type" has changed:
    return initial_media_type != *media_type;
}

} // namespace MediaTypeUtil
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/ValuePrinterInfo.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Value.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/ExecutionEngine/GenericValue.h"

#include <string>
#include <sstream>
#include <cstdio>

// Fragment copied from LLVM's raw_ostream.cpp
#if defined(_MSC_VER)
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
#else
//#if defined(HAVE_UNISTD_H)
# include <unistd.h>
//#endif
#endif

using namespace cling;

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*clang::Expr**/ E,
                      void* /*clang::ASTContext**/ C,
                      const void* value) {
  clang::Expr* Exp = (clang::Expr*)E;
  clang::ASTContext* Context = (clang::ASTContext*)C;
  ValuePrinterInfo VPI(Exp->getType(), Context);

  // We need stream that doesn't close its file descriptor, thus we are not
  // using llvm::outs. Keeping file descriptor open we will be able to use
  // the results in pipes (Savannah #99234).
  llvm::raw_fd_ostream outs (STDOUT_FILENO, /*ShouldClose*/false);

  valuePrinterInternal::flushToStream(outs, printType(value, value, VPI)
                                      + printValue(value, value, VPI));
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const ValuePrinterInfo& VPI);

static void StreamChar(llvm::raw_ostream& o, const char v) {
  if (isprint(v))
    o << '"' << v << "\"";
  else {
    o << "\\0x";
    o.write_hex(v);
  }
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v) {
  if (!v) {
    o << "<<<NULL>>>";
    return;
  }
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"...";
  else o << "\"";
}

static void StreamRef(llvm::raw_ostream& o, const void* v) {
  o <<"&" << v;
}

static void StreamPtr(llvm::raw_ostream& o, const void* v) {
  o << v;
}

static void StreamArr(llvm::raw_ostream& o, const void* p,
                      const ValuePrinterInfo& VPI) {
  const clang::QualType& Ty = VPI.getType();
  clang::ASTContext& C = *VPI.getASTContext();
  const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe();
  clang::QualType ElementTy = ArrTy->getElementType();
  if (ElementTy->isCharType())
    StreamCharPtr(o, (const char*)p);
  else if (Ty->isConstantArrayType()) {
    // Stream a constant array by streaming up to 5 elements.
    const clang::ConstantArrayType* CArrTy
      = C.getAsConstantArrayType(Ty);
    const llvm::APInt& APSize = CArrTy->getSize();
    size_t ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth();
    size_t Size = (size_t)APSize.getZExtValue();
    o << "{ ";
    ValuePrinterInfo ElVPI(ElementTy, &C);
    for (size_t i = 0; i < Size; ++i) {
      StreamValue(o, ((const char*)p) + i * ElBytes, ElVPI);
      if (i + 1 < Size) {
        if (i == 4) {
          o << "...";
          break;
        }
        else o << ", ";
      }
    }
    o << " }";
  } else
    StreamPtr(o, p);
}

static void StreamFunction(llvm::raw_ostream& o, const void* addr,
                           ValuePrinterInfo VPI) {
  o << "Function @" << addr << '\n';

  const clang::DeclRefExpr* DeclRefExp
    = llvm::dyn_cast_or_null<clang::DeclRefExpr>(VPI.getExpr());
  const clang::FunctionDecl* FD = 0;
  if (DeclRefExp)
    FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(DeclRefExp->getDecl());
  if (FD) {
    clang::SourceRange SRange = FD->getSourceRange();
    const char* cBegin = 0;
    const char* cEnd = 0;
    bool Invalid;
    if (SRange.isValid()) {
      clang::SourceManager& SM = VPI.getASTContext()->getSourceManager();
      clang::SourceLocation LocBegin = SRange.getBegin();
      LocBegin = SM.getExpansionRange(LocBegin).first;
      o << "  at " << SM.getFilename(LocBegin);
      unsigned LineNo = SM.getSpellingLineNumber(LocBegin, &Invalid);
      if (!Invalid)
        o << ':' << LineNo;
      o << ":\n";
      bool Invalid = false;
      cBegin = SM.getCharacterData(LocBegin, &Invalid);
      if (!Invalid) {
        clang::SourceLocation LocEnd = SRange.getEnd();
        LocEnd = SM.getExpansionRange(LocEnd).second;
        cEnd = SM.getCharacterData(LocEnd, &Invalid);
        if (Invalid)
          cBegin = 0;
      } else {
        cBegin = 0;
      }
    }
    if (cBegin && cEnd && cEnd > cBegin && cEnd - cBegin < 16 * 1024) {
      o << llvm::StringRef(cBegin, cEnd - cBegin + 1);
    } else {
      const clang::FunctionDecl* FDef;
      if (FD->hasBody(FDef))
        FD = FDef;
      FD->print(o);
      //const clang::FunctionDecl* FD
      //  = llvm::cast<const clang::FunctionType>(Ty)->getDecl();
    }
  } else {
    o << ":\n";
    // type-based printing:
    VPI.getType().print(o, VPI.getASTContext()->getPrintingPolicy());
  }
  // type-based print() never and decl-based print() sometimes does not include
  // a final newline:
  o << '\n';
}

static void StreamLongDouble(llvm::raw_ostream& o, const Value* value,
                             clang::ASTContext& C) {
  llvm::APFloat LDbl(C.getFloatTypeSemantics(value->getClangType()),
                     value->getGV().IntVal);
  llvm::SmallString<24> Buf;
  LDbl.toString(Buf);
  o << Buf << 'L';
}

static void StreamClingValue(llvm::raw_ostream& o, const Value* value,
                             clang::ASTContext& C) {
  if (!value || !value->isValid()) {
    o << "<<<invalid>>> @" << value;
  } else {
    o << "boxes [";
    o << "("
      << value->getClangType().getAsString(C.getPrintingPolicy())
      << ") ";
    clang::QualType valType = value->getClangType().getDesugaredType(C);
    if (C.hasSameType(valType, C.LongDoubleTy))
      StreamLongDouble(o, value, C);
    else if (valType->isFloatingType())
      o << value->getGV().DoubleVal;
    else if (valType->isIntegerType())
      o << value->getGV().IntVal.getSExtValue();
    else if (valType->isBooleanType())
      o << value->getGV().IntVal.getBoolValue();
    else
      StreamValue(o, value->getGV().PointerVal,
                  ValuePrinterInfo(valType, &C));
    o << "]";
  }
}

static void StreamObj(llvm::raw_ostream& o, const void* v,
                      const ValuePrinterInfo& VPI) {
  const clang::Type* Ty = VPI.getType().getTypePtr();
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) {
    std::string QualName = CXXRD->getQualifiedNameAsString();
    if (QualName == "cling::StoredValueRef"){
      valuePrinterInternal::StreamStoredValueRef(o, (const StoredValueRef*)v,
                                                 *VPI.getASTContext());
      return;
    } else if (QualName == "cling::Value") {
      StreamClingValue(o, (const Value*)v, *VPI.getASTContext());
      return;
    }
  } // if CXXRecordDecl

  // TODO: Print the object members.
  o << "@" << v;
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const ValuePrinterInfo& VPI) {
  clang::ASTContext& C = *VPI.getASTContext();
  clang::QualType Ty = VPI.getType().getDesugaredType(C);
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(const bool*)p) o << "true";
      else o << "false"; break;
    case clang::BuiltinType::Char_U:
    case clang::BuiltinType::UChar:
    case clang::BuiltinType::Char_S:
    case clang::BuiltinType::SChar:  StreamChar(o, *(const char*)p); break;
    case clang::BuiltinType::Short:  o << *(const short*)p; break;
    case clang::BuiltinType::UShort:
      o << *(const unsigned short*)p;
      break;
    case clang::BuiltinType::Int:    o << *(const int*)p; break;
    case clang::BuiltinType::UInt:
      o << *(const unsigned int*)p;
      break;
    case clang::BuiltinType::Long:   o << *(const long*)p; break;
    case clang::BuiltinType::ULong:
      o << *(const unsigned long*)p;
      break;
    case clang::BuiltinType::LongLong:
      o << *(const long long*)p;
      break;
    case clang::BuiltinType::ULongLong:
      o << *(const unsigned long long*)p;
      break;
    case clang::BuiltinType::Float:  o << *(const float*)p; break;
    case clang::BuiltinType::Double: o << *(const double*)p; break;
    case clang::BuiltinType::LongDouble: {
      std::stringstream ssLD;
      ssLD << *(const long double*)p;
      o << ssLD.str() << 'L'; break;
    }
    default:
      StreamObj(o, p, ValuePrinterInfo(Ty, &C));
    }
  }
  else if (Ty.getAsString().compare("class std::basic_string<char>") == 0
           || Ty.getAsString().compare("class std::__1::basic_string<char, "
                                       "struct std::__1::char_traits<char>, "
                                       "class std::__1::allocator<char> >")
           == 0) {
    StreamObj(o, p, ValuePrinterInfo(Ty, &C));
    o << " "; // force a space
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()));
  }
  else if (Ty->isEnumeralType()) {
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(const uint64_t*)p;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10);
  }
  else if (Ty->isReferenceType())
    StreamRef(o, p);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)p);
    else
      StreamPtr(o, p);
  }
  else if (Ty->isArrayType())
    StreamArr(o, p, ValuePrinterInfo(Ty, &C));
  else if (Ty->isFunctionType())
     StreamFunction(o, p, VPI);
  else
    StreamObj(o, p, ValuePrinterInfo(Ty, &C));
}

namespace cling {
namespace valuePrinterInternal {
  std::string printValue_Default(const void* const p,
                                 const ValuePrinterInfo& VPI) {
    std::string buf;
    {
      llvm::raw_string_ostream o(buf);
      StreamValue(o, p, VPI);
    }
    return buf;
  }

  std::string printType_Default(const ValuePrinterInfo& VPI) {
    std::string buf;
    {
      llvm::raw_string_ostream o(buf);
      o << "(";
      o << VPI.getType().getAsString();
      o << ") ";
    }
    return buf;
  }

  void StreamStoredValueRef(llvm::raw_ostream& o,
                            const StoredValueRef* VR,
                            clang::ASTContext& C) {
    if (VR->isValid()) {
      StreamClingValue(o, &VR->get(), C);
    } else {
      o << "<<<invalid>>> @" << VR;
    }
  }

  void flushToStream(llvm::raw_ostream& o, const std::string& s) {
    // We want to keep stdout and o in sync if o is different from stdout.
    fflush(stdout);
    o << s;
    o.flush();
  }
} // end namespace valuePrinterInternal
} // end namespace cling
<commit_msg>Stream refs by streaming the ref'ed object.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "cling/Interpreter/ValuePrinter.h"

#include "cling/Interpreter/CValuePrinter.h"
#include "cling/Interpreter/ValuePrinterInfo.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Value.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/ExecutionEngine/GenericValue.h"

#include <string>
#include <sstream>
#include <cstdio>

// Fragment copied from LLVM's raw_ostream.cpp
#if defined(_MSC_VER)
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
# define STDERR_FILENO 2
#endif
#else
//#if defined(HAVE_UNISTD_H)
# include <unistd.h>
//#endif
#endif

using namespace cling;

// Implements the CValuePrinter interface.
extern "C" void cling_PrintValue(void* /*clang::Expr**/ E,
                      void* /*clang::ASTContext**/ C,
                      const void* value) {
  clang::Expr* Exp = (clang::Expr*)E;
  clang::ASTContext* Context = (clang::ASTContext*)C;
  ValuePrinterInfo VPI(Exp->getType(), Context);

  // We need stream that doesn't close its file descriptor, thus we are not
  // using llvm::outs. Keeping file descriptor open we will be able to use
  // the results in pipes (Savannah #99234).
  llvm::raw_fd_ostream outs (STDOUT_FILENO, /*ShouldClose*/false);

  valuePrinterInternal::flushToStream(outs, printType(value, value, VPI)
                                      + printValue(value, value, VPI));
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const ValuePrinterInfo& VPI);

static void StreamChar(llvm::raw_ostream& o, const char v) {
  if (isprint(v))
    o << '"' << v << "\"";
  else {
    o << "\\0x";
    o.write_hex(v);
  }
}

static void StreamCharPtr(llvm::raw_ostream& o, const char* const v) {
  if (!v) {
    o << "<<<NULL>>>";
    return;
  }
  o << '"';
  const char* p = v;
  for (;*p && p - v < 128; ++p) {
    o << *p;
  }
  if (*p) o << "\"...";
  else o << "\"";
}

static void StreamRef(llvm::raw_ostream& o, const void* v,
                      const ValuePrinterInfo& VPI) {
  const clang::ReferenceType* RTy
    = llvm::dyn_cast<clang::ReferenceType>(VPI.getType().getTypePtr());
  ValuePrinterInfo VPIRefed(RTy->getPointeeType(), VPI.getASTContext());
  StreamValue(o, v, VPIRefed);
}

static void StreamPtr(llvm::raw_ostream& o, const void* v) {
  o << v;
}

static void StreamArr(llvm::raw_ostream& o, const void* p,
                      const ValuePrinterInfo& VPI) {
  const clang::QualType& Ty = VPI.getType();
  clang::ASTContext& C = *VPI.getASTContext();
  const clang::ArrayType* ArrTy = Ty->getAsArrayTypeUnsafe();
  clang::QualType ElementTy = ArrTy->getElementType();
  if (ElementTy->isCharType())
    StreamCharPtr(o, (const char*)p);
  else if (Ty->isConstantArrayType()) {
    // Stream a constant array by streaming up to 5 elements.
    const clang::ConstantArrayType* CArrTy
      = C.getAsConstantArrayType(Ty);
    const llvm::APInt& APSize = CArrTy->getSize();
    size_t ElBytes = C.getTypeSize(ElementTy) / C.getCharWidth();
    size_t Size = (size_t)APSize.getZExtValue();
    o << "{ ";
    ValuePrinterInfo ElVPI(ElementTy, &C);
    for (size_t i = 0; i < Size; ++i) {
      StreamValue(o, ((const char*)p) + i * ElBytes, ElVPI);
      if (i + 1 < Size) {
        if (i == 4) {
          o << "...";
          break;
        }
        else o << ", ";
      }
    }
    o << " }";
  } else
    StreamPtr(o, p);
}

static void StreamFunction(llvm::raw_ostream& o, const void* addr,
                           ValuePrinterInfo VPI) {
  o << "Function @" << addr << '\n';

  const clang::DeclRefExpr* DeclRefExp
    = llvm::dyn_cast_or_null<clang::DeclRefExpr>(VPI.getExpr());
  const clang::FunctionDecl* FD = 0;
  if (DeclRefExp)
    FD = llvm::dyn_cast_or_null<clang::FunctionDecl>(DeclRefExp->getDecl());
  if (FD) {
    clang::SourceRange SRange = FD->getSourceRange();
    const char* cBegin = 0;
    const char* cEnd = 0;
    bool Invalid;
    if (SRange.isValid()) {
      clang::SourceManager& SM = VPI.getASTContext()->getSourceManager();
      clang::SourceLocation LocBegin = SRange.getBegin();
      LocBegin = SM.getExpansionRange(LocBegin).first;
      o << "  at " << SM.getFilename(LocBegin);
      unsigned LineNo = SM.getSpellingLineNumber(LocBegin, &Invalid);
      if (!Invalid)
        o << ':' << LineNo;
      o << ":\n";
      bool Invalid = false;
      cBegin = SM.getCharacterData(LocBegin, &Invalid);
      if (!Invalid) {
        clang::SourceLocation LocEnd = SRange.getEnd();
        LocEnd = SM.getExpansionRange(LocEnd).second;
        cEnd = SM.getCharacterData(LocEnd, &Invalid);
        if (Invalid)
          cBegin = 0;
      } else {
        cBegin = 0;
      }
    }
    if (cBegin && cEnd && cEnd > cBegin && cEnd - cBegin < 16 * 1024) {
      o << llvm::StringRef(cBegin, cEnd - cBegin + 1);
    } else {
      const clang::FunctionDecl* FDef;
      if (FD->hasBody(FDef))
        FD = FDef;
      FD->print(o);
      //const clang::FunctionDecl* FD
      //  = llvm::cast<const clang::FunctionType>(Ty)->getDecl();
    }
  } else {
    o << ":\n";
    // type-based printing:
    VPI.getType().print(o, VPI.getASTContext()->getPrintingPolicy());
  }
  // type-based print() never and decl-based print() sometimes does not include
  // a final newline:
  o << '\n';
}

static void StreamLongDouble(llvm::raw_ostream& o, const Value* value,
                             clang::ASTContext& C) {
  llvm::APFloat LDbl(C.getFloatTypeSemantics(value->getClangType()),
                     value->getGV().IntVal);
  llvm::SmallString<24> Buf;
  LDbl.toString(Buf);
  o << Buf << 'L';
}

static void StreamClingValue(llvm::raw_ostream& o, const Value* value,
                             clang::ASTContext& C) {
  if (!value || !value->isValid()) {
    o << "<<<invalid>>> @" << value;
  } else {
    o << "boxes [";
    o << "("
      << value->getClangType().getAsString(C.getPrintingPolicy())
      << ") ";
    clang::QualType valType = value->getClangType().getDesugaredType(C);
    if (C.hasSameType(valType, C.LongDoubleTy))
      StreamLongDouble(o, value, C);
    else if (valType->isFloatingType())
      o << value->getGV().DoubleVal;
    else if (valType->isIntegerType())
      o << value->getGV().IntVal.getSExtValue();
    else if (valType->isBooleanType())
      o << value->getGV().IntVal.getBoolValue();
    else
      StreamValue(o, value->getGV().PointerVal,
                  ValuePrinterInfo(valType, &C));
    o << "]";
  }
}

static void StreamObj(llvm::raw_ostream& o, const void* v,
                      const ValuePrinterInfo& VPI) {
  const clang::Type* Ty = VPI.getType().getTypePtr();
  if (clang::CXXRecordDecl* CXXRD = Ty->getAsCXXRecordDecl()) {
    std::string QualName = CXXRD->getQualifiedNameAsString();
    if (QualName == "cling::StoredValueRef"){
      valuePrinterInternal::StreamStoredValueRef(o, (const StoredValueRef*)v,
                                                 *VPI.getASTContext());
      return;
    } else if (QualName == "cling::Value") {
      StreamClingValue(o, (const Value*)v, *VPI.getASTContext());
      return;
    }
  } // if CXXRecordDecl

  // TODO: Print the object members.
  o << "@" << v;
}

static void StreamValue(llvm::raw_ostream& o, const void* const p,
                        const ValuePrinterInfo& VPI) {
  clang::ASTContext& C = *VPI.getASTContext();
  clang::QualType Ty = VPI.getType().getDesugaredType(C);
  if (const clang::BuiltinType *BT
           = llvm::dyn_cast<clang::BuiltinType>(Ty.getCanonicalType())) {
    switch (BT->getKind()) {
    case clang::BuiltinType::Bool:
      if (*(const bool*)p) o << "true";
      else o << "false"; break;
    case clang::BuiltinType::Char_U:
    case clang::BuiltinType::UChar:
    case clang::BuiltinType::Char_S:
    case clang::BuiltinType::SChar:  StreamChar(o, *(const char*)p); break;
    case clang::BuiltinType::Short:  o << *(const short*)p; break;
    case clang::BuiltinType::UShort:
      o << *(const unsigned short*)p;
      break;
    case clang::BuiltinType::Int:    o << *(const int*)p; break;
    case clang::BuiltinType::UInt:
      o << *(const unsigned int*)p;
      break;
    case clang::BuiltinType::Long:   o << *(const long*)p; break;
    case clang::BuiltinType::ULong:
      o << *(const unsigned long*)p;
      break;
    case clang::BuiltinType::LongLong:
      o << *(const long long*)p;
      break;
    case clang::BuiltinType::ULongLong:
      o << *(const unsigned long long*)p;
      break;
    case clang::BuiltinType::Float:  o << *(const float*)p; break;
    case clang::BuiltinType::Double: o << *(const double*)p; break;
    case clang::BuiltinType::LongDouble: {
      std::stringstream ssLD;
      ssLD << *(const long double*)p;
      o << ssLD.str() << 'L'; break;
    }
    default:
      StreamObj(o, p, ValuePrinterInfo(Ty, &C));
    }
  }
  else if (Ty.getAsString().compare("class std::basic_string<char>") == 0
           || Ty.getAsString().compare("class std::__1::basic_string<char, "
                                       "struct std::__1::char_traits<char>, "
                                       "class std::__1::allocator<char> >")
           == 0) {
    StreamObj(o, p, ValuePrinterInfo(Ty, &C));
    o << " "; // force a space
    o <<"c_str: ";
    StreamCharPtr(o, ((const char*) (*(const std::string*)p).c_str()));
  }
  else if (Ty->isEnumeralType()) {
    clang::EnumDecl* ED = Ty->getAs<clang::EnumType>()->getDecl();
    uint64_t value = *(const uint64_t*)p;
    bool IsFirst = true;
    llvm::APSInt ValAsAPSInt = C.MakeIntValue(value, Ty);
    for (clang::EnumDecl::enumerator_iterator I = ED->enumerator_begin(),
           E = ED->enumerator_end(); I != E; ++I) {
      if (I->getInitVal() == ValAsAPSInt) {
        if (!IsFirst) {
          o << " ? ";
        }
        o << "(" << I->getQualifiedNameAsString() << ")";
        IsFirst = false;
      }
    }
    o << " : (int) " << ValAsAPSInt.toString(/*Radix = */10);
  }
  else if (Ty->isReferenceType())
    StreamRef(o, p, VPI);
  else if (Ty->isPointerType()) {
    clang::QualType PointeeTy = Ty->getPointeeType();
    if (PointeeTy->isCharType())
      StreamCharPtr(o, (const char*)p);
    else
      StreamPtr(o, p);
  }
  else if (Ty->isArrayType())
    StreamArr(o, p, ValuePrinterInfo(Ty, &C));
  else if (Ty->isFunctionType())
     StreamFunction(o, p, VPI);
  else
    StreamObj(o, p, ValuePrinterInfo(Ty, &C));
}

namespace cling {
namespace valuePrinterInternal {
  std::string printValue_Default(const void* const p,
                                 const ValuePrinterInfo& VPI) {
    std::string buf;
    {
      llvm::raw_string_ostream o(buf);
      StreamValue(o, p, VPI);
    }
    return buf;
  }

  std::string printType_Default(const ValuePrinterInfo& VPI) {
    std::string buf;
    {
      llvm::raw_string_ostream o(buf);
      o << "(";
      o << VPI.getType().getAsString();
      o << ") ";
    }
    return buf;
  }

  void StreamStoredValueRef(llvm::raw_ostream& o,
                            const StoredValueRef* VR,
                            clang::ASTContext& C) {
    if (VR->isValid()) {
      StreamClingValue(o, &VR->get(), C);
    } else {
      o << "<<<invalid>>> @" << VR;
    }
  }

  void flushToStream(llvm::raw_ostream& o, const std::string& s) {
    // We want to keep stdout and o in sync if o is different from stdout.
    fflush(stdout);
    o << s;
    o.flush();
  }
} // end namespace valuePrinterInternal
} // end namespace cling
<|endoftext|>


<commit_before>/*
 * Copyright (c) 1999-2004 Sourceforge JACOB Project.
 * All rights reserved. Originator: Dan Adler (http://danadler.com).
 * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "stdafx.h"
#include <objbase.h>
#include "Dispatch.h"
// Win32 support for Ole Automation
#include <wchar.h>
#include <string.h>
#include <atlbase.h>
#include <oleauto.h>
#include <olectl.h>
#include "util.h"

extern "C" {

JNIEXPORT jint JNICALL Java_com_jacob_com_IUnknown_toEnumVariant
  (JNIEnv *env, jobject obj, jint pointer) {
    IDispatch *dispatch = (IDispatch *) pointer;
    LCID lcid = 2048; // <--- heh
    unsigned int argErr;
    EXCEPINFO excepinfo;
    DISPPARAMS dispParams;
    VARIANT result;
    IEnumVARIANT *pEnum = NULL;

    VariantInit(&result);
    dispParams.rgvarg = NULL;
    dispParams.rgdispidNamedArgs = NULL;
    dispParams.cNamedArgs = 0;
    dispParams.cArgs = 0;
    memset(&excepinfo, 0, sizeof(excepinfo));
    HRESULT hr = dispatch->Invoke(DISPID_NEWENUM, IID_NULL, lcid,
         DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dispParams, &result,
            &excepinfo, &argErr);

    if (FAILED(hr)) {
       VariantClear(&result);
       ThrowComFail(env, "failed to get IEnum Interface", hr);
    }

    if (V_VT(&result) == VT_UNKNOWN) {
        hr = V_UNKNOWN(&result)->QueryInterface(IID_IEnumVARIANT, (void **) &pEnum);
    } else if (V_VT(&result) == VT_DISPATCH) {
        hr = V_DISPATCH(&result)->QueryInterface(IID_IEnumVARIANT, (void **) &pEnum);
    }
    if (FAILED(hr) || !pEnum) {
       VariantClear(&result);
       ThrowComFail(env, "failed to get IEnum Interface", hr);
    }

    VariantClear(&result);

    return (jint) pEnum;
}

/*
 * Class:     IUnknown
 * Method:    release
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_jacob_com_IUnknown_release
  (JNIEnv *env, jclass obj, jint pointer) {
  IUnknown* self = (IUnknown *) pointer;
  if(self != NULL) self->Release();
}

}
<commit_msg>Mild retweaking<commit_after>/*
 * Copyright (c) 1999-2004 Sourceforge JACOB Project.
 * All rights reserved. Originator: Dan Adler (http://danadler.com).
 * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
#include "stdafx.h"
#include <objbase.h>
#include "Dispatch.h"
// Win32 support for Ole Automation
#include <wchar.h>
#include <string.h>
#include <atlbase.h>
#include <oleauto.h>
#include <olectl.h>
#include "util.h"

extern "C" {

JNIEXPORT jint JNICALL Java_com_jacob_com_IUnknown_toEnumVariant
  (JNIEnv *env, jobject obj, jint pointer) {
    IDispatch *dispatch = (IDispatch *) pointer;
    LCID lcid = 2048; // <--- heh
    unsigned int argErr;
    EXCEPINFO excepinfo;
    DISPPARAMS dispParams;
    VARIANT result;
    IEnumVARIANT *pEnum = NULL;

    VariantInit(&result);
    dispParams.rgvarg = NULL;
    dispParams.rgdispidNamedArgs = NULL;
    dispParams.cNamedArgs = 0;
    dispParams.cArgs = 0;
    memset(&excepinfo, 0, sizeof(excepinfo));
    HRESULT hr = dispatch->Invoke(DISPID_NEWENUM, IID_NULL, lcid,
         DISPATCH_METHOD | DISPATCH_PROPERTYGET, &dispParams, &result,
            &excepinfo, &argErr);

    if (FAILED(hr)) {
       VariantClear(&result);
       ThrowComFail(env, "failed to get IEnum Interface", hr);
    }

    if (V_VT(&result) == VT_UNKNOWN) {
        hr = V_UNKNOWN(&result)->QueryInterface(IID_IEnumVARIANT, (void **) &pEnum);
    } else if (V_VT(&result) == VT_DISPATCH) {
        hr = V_DISPATCH(&result)->QueryInterface(IID_IEnumVARIANT, (void **) &pEnum);
    }
    VariantClear(&result);

    if (FAILED(hr) || !pEnum) ThrowComFail(env, "failed to get IEnum Interface", hr);

    return (jint) pEnum;
}

/*
 * Class:     IUnknown
 * Method:    release
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_jacob_com_IUnknown_release
  (JNIEnv *env, jclass obj, jint pointer) {
  IUnknown* self = (IUnknown *) pointer;
  if(self != NULL) self->Release();
}

}
<|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 "chrome/browser/chromeos/login/user_view.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/login/rounded_view.h"
#include "gfx/canvas.h"
#include "gfx/canvas_skia.h"
#include "gfx/rect.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/background.h"
#include "views/controls/button/text_button.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/controls/link.h"
#include "views/painter.h"

namespace {

// Background color and corner radius of the login status label and
// signout button.
const SkColor kSignoutBackgroundColor = 0xFF007700;
const int kSignoutBackgroundCornerRadius = 4;

// Horiz/Vert insets for Signout view.
const int kSignoutViewHorizontalInsets = 10;
const int kSignoutViewVerticalInsets = 5;

// Padding between remove button and top right image corner.
const int kRemoveButtonPadding = 3;

// Draws green-ish background for signout view with
// rounded corners at the bottom.
class SignoutBackgroundPainter : public views::Painter {
  virtual void Paint(int w, int h, gfx::Canvas* canvas) {
    SkRect rect = {0, 0, w, h};
    SkPath path;
    SkScalar corners[] = {
      0, 0,
      0, 0,
      kSignoutBackgroundCornerRadius,
      kSignoutBackgroundCornerRadius,
      kSignoutBackgroundCornerRadius,
      kSignoutBackgroundCornerRadius,
    };
    path.addRoundRect(rect, corners);
    SkPaint paint;
    paint.setStyle(SkPaint::kFill_Style);
    paint.setFlags(SkPaint::kAntiAlias_Flag);
    paint.setColor(kSignoutBackgroundColor);
    canvas->AsCanvasSkia()->drawPath(path, paint);
  }
};

}  // namespace

namespace chromeos {

using login::kBackgroundColor;
using login::kTextColor;
using login::kUserImageSize;

// The view that shows the Sign out button below the user's image.
class SignoutView : public views::View {
 public:
  explicit SignoutView(views::LinkController* link_controller) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    const gfx::Font& font = rb.GetFont(ResourceBundle::SmallFont);

    active_user_label_ = new views::Label(
        l10n_util::GetString(IDS_SCREEN_LOCK_ACTIVE_USER));
    active_user_label_->SetFont(font);
    active_user_label_->SetColor(kTextColor);

    signout_link_ = new views::Link(
        l10n_util::GetString(IDS_SCREEN_LOCK_SIGN_OUT));
    signout_link_->SetController(link_controller);
    signout_link_->SetFont(font);
    signout_link_->SetColor(kTextColor);
    signout_link_->SetFocusable(true);

    AddChildView(active_user_label_);
    AddChildView(signout_link_);

    set_background(views::Background::CreateBackgroundPainter(
        true, new SignoutBackgroundPainter()));
  }

  // views::View overrides.
  virtual void Layout() {
    gfx::Size label = active_user_label_->GetPreferredSize();
    gfx::Size button = signout_link_->GetPreferredSize();
    active_user_label_->SetBounds(
        kSignoutViewHorizontalInsets, (height() - label.height()) / 2,
        label.width(), label.height());
    signout_link_->SetBounds(
        width() - button.width() - kSignoutViewHorizontalInsets,
        (height() - button.height()) / 2,
        button.width(), button.height());
  }

  virtual gfx::Size GetPreferredSize() {
    gfx::Size label = active_user_label_->GetPreferredSize();
    gfx::Size button = signout_link_->GetPreferredSize();
    return gfx::Size(label.width() + button.width(),
                     std::max(label.height(), button.height()) +
                     kSignoutViewVerticalInsets * 2);
  }

  views::Link* signout_link() { return signout_link_; }

 private:
  friend class UserView;

  views::Label* active_user_label_;
  views::Link* signout_link_;

  DISALLOW_COPY_AND_ASSIGN(SignoutView);
};

class RemoveButton : public views::TextButton {
 public:
  RemoveButton(views::ButtonListener* listener,
               const SkBitmap& icon,
               const std::wstring& text,
               const gfx::Point& top_right)
    : views::TextButton(listener, std::wstring()),
      icon_(icon),
      text_(text),
      top_right_(top_right),
      was_first_click_(false) {
    SetEnabledColor(SK_ColorWHITE);
    SetDisabledColor(SK_ColorWHITE);
    SetHighlightColor(SK_ColorWHITE);
    SetHoverColor(SK_ColorWHITE);
    SetIcon(icon_);
    UpdatePosition();
  }

 protected:
  // Overridden from View:
  virtual void OnMouseExited(const views::MouseEvent& event) {
    SetIcon(icon_);
    views::TextButton::SetText(std::wstring());
    ClearMaxTextSize();
    set_background(NULL);
    set_border(new views::TextButtonBorder);
    UpdatePosition();
    views::TextButton::OnMouseExited(event);
    was_first_click_ = false;
  }

  void NotifyClick(const views::Event& event) {
    if (!was_first_click_) {
      // On first click transform image to "remove" label.
      SetIcon(SkBitmap());
      views::TextButton::SetText(text_);

      const SkColor kStrokeColor = SK_ColorWHITE;
      const SkColor kButtonColor = 0xFFE94949;
      const int kStrokeWidth = 1;
      const int kVerticalPadding = 4;
      const int kHorizontalPadding = 8;
      const int kCornerRadius = 4;

      set_background(
          CreateRoundedBackground(
              kCornerRadius, kStrokeWidth, kButtonColor, kStrokeColor));

      set_border(
          views::Border::CreateEmptyBorder(kVerticalPadding,
                                           kHorizontalPadding,
                                           kVerticalPadding,
                                           kHorizontalPadding));

      UpdatePosition();
      was_first_click_ = true;
    } else {
      // On second click propagate to base class to fire ButtonPressed.
      views::TextButton::NotifyClick(event);
    }
  }

  void SetText(const std::wstring& text) {
    text_ = text;
  }

 private:
  // Update button position and schedule paint event for the view and parent.
  void UpdatePosition() {
    gfx::Size size = GetPreferredSize();
    gfx::Point origin = top_right_;
    origin.Offset(-size.width(), 0);
    SetBounds(gfx::Rect(origin, size));

    if (GetParent())
      GetParent()->SchedulePaint();
  }

  SkBitmap icon_;
  std::wstring text_;
  gfx::Point top_right_;
  bool was_first_click_;

  DISALLOW_COPY_AND_ASSIGN(RemoveButton);
};

class PodImageView : public views::ImageView {
 public:
  PodImageView() { }

  void SetImage(const SkBitmap& image, const SkBitmap& image_hot) {
    image_ = image;
    image_hot_ = image_hot;
    views::ImageView::SetImage(image_);
  }

 protected:
  // Overridden from View:
  virtual void OnMouseEntered(const views::MouseEvent& event) {
    views::ImageView::SetImage(image_hot_);
  }

  virtual void OnMouseExited(const views::MouseEvent& event) {
    views::ImageView::SetImage(image_);
  }

 private:
  SkBitmap image_;
  SkBitmap image_hot_;

  DISALLOW_COPY_AND_ASSIGN(PodImageView);
};

UserView::UserView(Delegate* delegate, bool is_login, bool need_background)
    : delegate_(delegate),
      signout_view_(NULL),
      image_view_(NULL),
      remove_button_(NULL) {
  DCHECK(delegate);
  if (!is_login)
    signout_view_ = new SignoutView(this);

  if (need_background)
    image_view_ = new RoundedView<PodImageView>;
  else
    image_view_ = new PodImageView;

  Init(need_background);
}

void UserView::Init(bool need_background) {
  if (need_background) {
    image_view_->set_background(
        views::Background::CreateSolidBackground(kBackgroundColor));
  }

  // UserView's layout never changes, so let's layout once here.
  image_view_->SetBounds(0, 0, kUserImageSize, kUserImageSize);
  AddChildView(image_view_);

  if (signout_view_) {
    signout_view_->SetBounds(0, kUserImageSize, kUserImageSize,
                             signout_view_->GetPreferredSize().height());
    AddChildView(signout_view_);
  }

  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  remove_button_ = new RemoveButton(
      this,
      *rb.GetBitmapNamed(IDR_CLOSE_BAR_H),
      l10n_util::GetString(IDS_LOGIN_REMOVE),
      gfx::Point(kUserImageSize - kRemoveButtonPadding, kRemoveButtonPadding));
  remove_button_->SetVisible(false);
  AddChildView(remove_button_);
}

void UserView::SetImage(const SkBitmap& image, const SkBitmap& image_hot) {
  int desired_size = std::min(image.width(), image.height());
  // Desired size is not preserved if it's greater than 75% of kUserImageSize.
  if (desired_size * 4 > 3 * kUserImageSize)
    desired_size = kUserImageSize;
  image_view_->SetImageSize(gfx::Size(desired_size, desired_size));
  image_view_->SetImage(image, image_hot);
}

void UserView::SetTooltipText(const std::wstring& text) {
  DCHECK(image_view_);
  image_view_->SetTooltipText(text);
}

gfx::Size UserView::GetPreferredSize() {
  return gfx::Size(
      kUserImageSize,
      kUserImageSize +
      (signout_view_ ? signout_view_->GetPreferredSize().height() : 0));
}

void UserView::SetSignoutEnabled(bool enabled) {
  DCHECK(signout_view_);
  signout_view_->signout_link_->SetEnabled(enabled);
}

void UserView::LinkActivated(views::Link* source, int event_flags) {
  DCHECK(delegate_);
  DCHECK(signout_view_);
  if (signout_view_->signout_link_ == source)
    delegate_->OnSignout();
}

void UserView::SetRemoveButtonVisible(bool flag) {
  remove_button_->SetVisible(flag);
}

void UserView::ButtonPressed(views::Button* sender, const views::Event& event) {
  DCHECK(delegate_);
  if (remove_button_ == sender)
    delegate_->OnRemoveUser();
}

void UserView::OnLocaleChanged() {
  remove_button_->SetText(l10n_util::GetString(IDS_LOGIN_REMOVE));
}

}  // namespace chromeos
<commit_msg>User pods show hand cursor on hover Re-applying from http://codereview.chromium.org/5986005/, LGTM is there.<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 "chrome/browser/chromeos/login/user_view.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/rounded_rect_painter.h"
#include "chrome/browser/chromeos/login/rounded_view.h"
#include "gfx/canvas.h"
#include "gfx/canvas_skia.h"
#include "gfx/gtk_util.h"
#include "gfx/rect.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "views/background.h"
#include "views/controls/button/text_button.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/controls/link.h"
#include "views/painter.h"

namespace {

// Background color and corner radius of the login status label and
// signout button.
const SkColor kSignoutBackgroundColor = 0xFF007700;
const int kSignoutBackgroundCornerRadius = 4;

// Horiz/Vert insets for Signout view.
const int kSignoutViewHorizontalInsets = 10;
const int kSignoutViewVerticalInsets = 5;

// Padding between remove button and top right image corner.
const int kRemoveButtonPadding = 3;

// Draws green-ish background for signout view with
// rounded corners at the bottom.
class SignoutBackgroundPainter : public views::Painter {
  virtual void Paint(int w, int h, gfx::Canvas* canvas) {
    SkRect rect = {0, 0, w, h};
    SkPath path;
    SkScalar corners[] = {
      0, 0,
      0, 0,
      kSignoutBackgroundCornerRadius,
      kSignoutBackgroundCornerRadius,
      kSignoutBackgroundCornerRadius,
      kSignoutBackgroundCornerRadius,
    };
    path.addRoundRect(rect, corners);
    SkPaint paint;
    paint.setStyle(SkPaint::kFill_Style);
    paint.setFlags(SkPaint::kAntiAlias_Flag);
    paint.setColor(kSignoutBackgroundColor);
    canvas->AsCanvasSkia()->drawPath(path, paint);
  }
};

}  // namespace

namespace chromeos {

using login::kBackgroundColor;
using login::kTextColor;
using login::kUserImageSize;

// The view that shows the Sign out button below the user's image.
class SignoutView : public views::View {
 public:
  explicit SignoutView(views::LinkController* link_controller) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    const gfx::Font& font = rb.GetFont(ResourceBundle::SmallFont);

    active_user_label_ = new views::Label(
        l10n_util::GetString(IDS_SCREEN_LOCK_ACTIVE_USER));
    active_user_label_->SetFont(font);
    active_user_label_->SetColor(kTextColor);

    signout_link_ = new views::Link(
        l10n_util::GetString(IDS_SCREEN_LOCK_SIGN_OUT));
    signout_link_->SetController(link_controller);
    signout_link_->SetFont(font);
    signout_link_->SetColor(kTextColor);
    signout_link_->SetFocusable(true);

    AddChildView(active_user_label_);
    AddChildView(signout_link_);

    set_background(views::Background::CreateBackgroundPainter(
        true, new SignoutBackgroundPainter()));
  }

  // views::View overrides.
  virtual void Layout() {
    gfx::Size label = active_user_label_->GetPreferredSize();
    gfx::Size button = signout_link_->GetPreferredSize();
    active_user_label_->SetBounds(
        kSignoutViewHorizontalInsets, (height() - label.height()) / 2,
        label.width(), label.height());
    signout_link_->SetBounds(
        width() - button.width() - kSignoutViewHorizontalInsets,
        (height() - button.height()) / 2,
        button.width(), button.height());
  }

  virtual gfx::Size GetPreferredSize() {
    gfx::Size label = active_user_label_->GetPreferredSize();
    gfx::Size button = signout_link_->GetPreferredSize();
    return gfx::Size(label.width() + button.width(),
                     std::max(label.height(), button.height()) +
                     kSignoutViewVerticalInsets * 2);
  }

  views::Link* signout_link() { return signout_link_; }

 private:
  friend class UserView;

  views::Label* active_user_label_;
  views::Link* signout_link_;

  DISALLOW_COPY_AND_ASSIGN(SignoutView);
};

class RemoveButton : public views::TextButton {
 public:
  RemoveButton(views::ButtonListener* listener,
               const SkBitmap& icon,
               const std::wstring& text,
               const gfx::Point& top_right)
    : views::TextButton(listener, std::wstring()),
      icon_(icon),
      text_(text),
      top_right_(top_right),
      was_first_click_(false) {
    SetEnabledColor(SK_ColorWHITE);
    SetDisabledColor(SK_ColorWHITE);
    SetHighlightColor(SK_ColorWHITE);
    SetHoverColor(SK_ColorWHITE);
    SetIcon(icon_);
    UpdatePosition();
  }

 protected:
  // Overridden from View:
  virtual void OnMouseExited(const views::MouseEvent& event) {
    SetIcon(icon_);
    views::TextButton::SetText(std::wstring());
    ClearMaxTextSize();
    set_background(NULL);
    set_border(new views::TextButtonBorder);
    UpdatePosition();
    views::TextButton::OnMouseExited(event);
    was_first_click_ = false;
  }

  void NotifyClick(const views::Event& event) {
    if (!was_first_click_) {
      // On first click transform image to "remove" label.
      SetIcon(SkBitmap());
      views::TextButton::SetText(text_);

      const SkColor kStrokeColor = SK_ColorWHITE;
      const SkColor kButtonColor = 0xFFE94949;
      const int kStrokeWidth = 1;
      const int kVerticalPadding = 4;
      const int kHorizontalPadding = 8;
      const int kCornerRadius = 4;

      set_background(
          CreateRoundedBackground(
              kCornerRadius, kStrokeWidth, kButtonColor, kStrokeColor));

      set_border(
          views::Border::CreateEmptyBorder(kVerticalPadding,
                                           kHorizontalPadding,
                                           kVerticalPadding,
                                           kHorizontalPadding));

      UpdatePosition();
      was_first_click_ = true;
    } else {
      // On second click propagate to base class to fire ButtonPressed.
      views::TextButton::NotifyClick(event);
    }
  }

  void SetText(const std::wstring& text) {
    text_ = text;
  }

 private:
  // Update button position and schedule paint event for the view and parent.
  void UpdatePosition() {
    gfx::Size size = GetPreferredSize();
    gfx::Point origin = top_right_;
    origin.Offset(-size.width(), 0);
    SetBounds(gfx::Rect(origin, size));

    if (GetParent())
      GetParent()->SchedulePaint();
  }

  SkBitmap icon_;
  std::wstring text_;
  gfx::Point top_right_;
  bool was_first_click_;

  DISALLOW_COPY_AND_ASSIGN(RemoveButton);
};

class PodImageView : public views::ImageView {
 public:
  PodImageView() { }

  void SetImage(const SkBitmap& image, const SkBitmap& image_hot) {
    image_ = image;
    image_hot_ = image_hot;
    views::ImageView::SetImage(image_);
  }

 protected:
  // Overridden from View:
  virtual void OnMouseEntered(const views::MouseEvent& event) {
    views::ImageView::SetImage(image_hot_);
  }

  virtual void OnMouseExited(const views::MouseEvent& event) {
    views::ImageView::SetImage(image_);
  }

  gfx::NativeCursor GetCursorForPoint(
      views::Event::EventType event_type,
      const gfx::Point& p) {
    return gfx::GetCursor(GDK_HAND2);
  }

 private:
  SkBitmap image_;
  SkBitmap image_hot_;

  DISALLOW_COPY_AND_ASSIGN(PodImageView);
};

UserView::UserView(Delegate* delegate, bool is_login, bool need_background)
    : delegate_(delegate),
      signout_view_(NULL),
      image_view_(NULL),
      remove_button_(NULL) {
  DCHECK(delegate);
  if (!is_login)
    signout_view_ = new SignoutView(this);

  if (need_background)
    image_view_ = new RoundedView<PodImageView>;
  else
    image_view_ = new PodImageView;

  Init(need_background);
}

void UserView::Init(bool need_background) {
  if (need_background) {
    image_view_->set_background(
        views::Background::CreateSolidBackground(kBackgroundColor));
  }

  // UserView's layout never changes, so let's layout once here.
  image_view_->SetBounds(0, 0, kUserImageSize, kUserImageSize);
  AddChildView(image_view_);

  if (signout_view_) {
    signout_view_->SetBounds(0, kUserImageSize, kUserImageSize,
                             signout_view_->GetPreferredSize().height());
    AddChildView(signout_view_);
  }

  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  remove_button_ = new RemoveButton(
      this,
      *rb.GetBitmapNamed(IDR_CLOSE_BAR_H),
      l10n_util::GetString(IDS_LOGIN_REMOVE),
      gfx::Point(kUserImageSize - kRemoveButtonPadding, kRemoveButtonPadding));
  remove_button_->SetVisible(false);
  AddChildView(remove_button_);
}

void UserView::SetImage(const SkBitmap& image, const SkBitmap& image_hot) {
  int desired_size = std::min(image.width(), image.height());
  // Desired size is not preserved if it's greater than 75% of kUserImageSize.
  if (desired_size * 4 > 3 * kUserImageSize)
    desired_size = kUserImageSize;
  image_view_->SetImageSize(gfx::Size(desired_size, desired_size));
  image_view_->SetImage(image, image_hot);
}

void UserView::SetTooltipText(const std::wstring& text) {
  DCHECK(image_view_);
  image_view_->SetTooltipText(text);
}

gfx::Size UserView::GetPreferredSize() {
  return gfx::Size(
      kUserImageSize,
      kUserImageSize +
      (signout_view_ ? signout_view_->GetPreferredSize().height() : 0));
}

void UserView::SetSignoutEnabled(bool enabled) {
  DCHECK(signout_view_);
  signout_view_->signout_link_->SetEnabled(enabled);
}

void UserView::LinkActivated(views::Link* source, int event_flags) {
  DCHECK(delegate_);
  DCHECK(signout_view_);
  if (signout_view_->signout_link_ == source)
    delegate_->OnSignout();
}

void UserView::SetRemoveButtonVisible(bool flag) {
  remove_button_->SetVisible(flag);
}

void UserView::ButtonPressed(views::Button* sender, const views::Event& event) {
  DCHECK(delegate_);
  if (remove_button_ == sender)
    delegate_->OnRemoveUser();
}

void UserView::OnLocaleChanged() {
  remove_button_->SetText(l10n_util::GetString(IDS_LOGIN_REMOVE));
}

}  // namespace chromeos
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: unourl.cxx,v $
 *
 *  $Revision: 1.1 $
 *
 *  last change: $Author: sb $ $Date: 2002-10-02 15:31:56 $
 *
 *  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: 2002 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "cppuhelper/unourl.hxx"

#include "osl/diagnose.h"
#include "rtl/malformeduriexception.hxx"
#include "rtl/string.h"
#include "rtl/textenc.h"
#include "rtl/uri.h"
#include "rtl/uri.hxx"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"

#include <map>

using cppu::UnoUrl;
using cppu::UnoUrlDescriptor;

namespace {

inline bool isAlphanum(sal_Unicode c)
{
    return c >= 0x30 && c <= 0x39 // '0'--'9'
        || c >= 0x41 && c <= 0x5A // 'A'--'Z'
        || c >= 0x61 && c <= 0x7A; // 'a'--'z'
}

}

class UnoUrlDescriptor::Impl
{
public:
    typedef std::map< rtl::OUString, rtl::OUString > Parameters;

    rtl::OUString m_aDescriptor;
    rtl::OUString m_aName;
    Parameters m_aParameters;

    /** @exception rtl::MalformedUriException
     */
    explicit inline Impl(rtl::OUString const & m_aDescriptor);

    inline Impl * clone() const { return new Impl(*this); }
};

inline UnoUrlDescriptor::Impl::Impl(rtl::OUString const & rDescriptor)
{
    m_aDescriptor = rDescriptor;
    enum State { STATE_NAME0, STATE_NAME, STATE_KEY0, STATE_KEY, STATE_VALUE };
    State eState = STATE_NAME0;
    sal_Int32 nStart;
    rtl::OUString aKey;
    for (sal_Int32 i = 0;; ++i)
    {
        bool bEnd = i == rDescriptor.getLength();
        sal_Unicode c = bEnd ? 0 : rDescriptor.getStr()[i];
        switch (eState)
        {
        case STATE_NAME0:
            if (bEnd || !isAlphanum(c))
                throw rtl::MalformedUriException(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                      "UNO URL contains bad descriptor name")));
            nStart = i;
            eState = STATE_NAME;
            break;

        case STATE_NAME:
            if (bEnd || c == 0x2C) // ','
            {
                m_aName
                    = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
                eState = STATE_KEY0;
            }
            else if (!isAlphanum(c))
                throw rtl::MalformedUriException(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                      "UNO URL contains bad descriptor name")));
            break;

        case STATE_KEY0:
            if (bEnd || !isAlphanum(c))
                throw rtl::MalformedUriException(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                      "UNO URL contains bad parameter key")));
            nStart = i;
            eState = STATE_KEY;
            break;

        case STATE_KEY:
            if (c == 0x3D) // '='
            {
                aKey = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
                nStart = i + 1;
                eState = STATE_VALUE;
            }
            else if (bEnd || !isAlphanum(c))
                throw rtl::MalformedUriException(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                      "UNO URL contains bad parameter key")));
            break;

        case STATE_VALUE:
            if (bEnd || c == 0x2C) // ','
            {
                if (!m_aParameters.insert(
                        Parameters::value_type(
                            aKey,
                            rtl::Uri::decode(rDescriptor.copy(nStart,
                                                              i - nStart),
                                             rtl_UriDecodeWithCharset,
                                             RTL_TEXTENCODING_UTF8))).second)
                    throw rtl::MalformedUriException(
                        rtl::OUString(
                            RTL_CONSTASCII_USTRINGPARAM(
                                "UNO URL contains duplicated parameter")));
                eState = STATE_KEY0;
            }
            break;
        }
        if (bEnd)
            break;
    }
}

UnoUrlDescriptor::UnoUrlDescriptor(rtl::OUString const & rDescriptor):
    m_xImpl(new Impl(rDescriptor))
{}

UnoUrlDescriptor::UnoUrlDescriptor(std::auto_ptr< Impl > & rImpl):
    m_xImpl(rImpl)
{}

UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor const & rOther):
    m_xImpl(rOther.m_xImpl->clone())
{}

UnoUrlDescriptor::~UnoUrlDescriptor()
{}

UnoUrlDescriptor & UnoUrlDescriptor::operator =(UnoUrlDescriptor const & rOther)
{
    m_xImpl.reset(rOther.m_xImpl->clone());
    return *this;
}

rtl::OUString const & UnoUrlDescriptor::getDescriptor() const
{
    return m_xImpl->m_aDescriptor;
}

rtl::OUString const & UnoUrlDescriptor::getName() const
{
    return m_xImpl->m_aName;
}

bool UnoUrlDescriptor::hasParameter(rtl::OUString const & rKey) const
{
    return m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase())
        != m_xImpl->m_aParameters.end();
}

rtl::OUString UnoUrlDescriptor::getParameter(rtl::OUString const & rKey) const
{
    Impl::Parameters::const_iterator
        aIt(m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase()));
    return aIt == m_xImpl->m_aParameters.end() ? rtl::OUString() : aIt->second;
}

class UnoUrl::Impl
{
public:
    UnoUrlDescriptor m_aConnection;
    UnoUrlDescriptor m_aProtocol;
    rtl::OUString m_aObjectName;

    inline Impl * clone() const { return new Impl(*this); }

    /** @exception rtl::MalformedUriException
     */
    static inline Impl * create(rtl::OUString const & rUrl);

private:
    inline Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection,
                std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol,
                rtl::OUString const & rObjectName);
};

inline UnoUrl::Impl::Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection,
                          std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol,
                          rtl::OUString const & rObjectName):
    m_aConnection(rConnection),
    m_aProtocol(rProtocol),
    m_aObjectName(rObjectName)
{}

inline UnoUrl::Impl * UnoUrl::Impl::create(rtl::OUString const & rUrl)
{
    if (!rUrl.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("uno:"), 0))
        throw rtl::MalformedUriException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                              "UNO URL does not start with \"uno:\"")));
    sal_Int32 i = RTL_CONSTASCII_LENGTH("uno:");
    sal_Int32 j = rUrl.indexOf(';', i);
    if (j < 0)
        throw rtl::MalformedUriException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                              "UNO URL has too few semicolons")));
    std::auto_ptr< UnoUrlDescriptor::Impl >
        xConnection(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i)));
    i = j + 1;
    j = rUrl.indexOf(0x3B, i); // ';'
    if (j < 0)
        throw rtl::MalformedUriException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                              "UNO URL has too few semicolons")));
    std::auto_ptr< UnoUrlDescriptor::Impl >
        xProtocol(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i)));
    i = j + 1;
    if (i == rUrl.getLength())
        throw rtl::MalformedUriException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                              "UNO URL contains empty ObjectName")));
    for (j = i; j < rUrl.getLength(); ++j)
    {
        sal_Unicode c = rUrl.getStr()[j];
        if (!isAlphanum(c) && c != 0x21 && c != 0x24 // '!', '$'
            && c != 0x26 && c != 0x27 && c != 0x28 // '&', ''', '('
            && c != 0x28 && c != 0x2A && c != 0x2B // ')', '*', '+'
            && c != 0x2C && c != 0x2D && c != 0x2E // ',', '-', '.'
            && c != 0x2F && c != 0x3A && c != 0x3D // '/', ':', '='
            && c != 0x3F && c != 0x40 && c != 0x5F // '?', '@', '_'
            && c != 0x7E) // '~'
            throw rtl::MalformedUriException(
                rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                  "UNO URL contains invalid ObjectName")));
    }
    return new Impl(xConnection, xProtocol, rUrl.copy(i));
}

UnoUrl::UnoUrl(rtl::OUString const & rUrl): m_xImpl(Impl::create(rUrl))
{}

UnoUrl::UnoUrl(UnoUrl const & rOther): m_xImpl(rOther.m_xImpl->clone())
{}

UnoUrl::~UnoUrl()
{}

UnoUrl & UnoUrl::operator =(UnoUrl const & rOther)
{
    m_xImpl.reset(rOther.m_xImpl->clone());
    return *this;
}

UnoUrlDescriptor const & UnoUrl::getConnection() const
{
    return m_xImpl->m_aConnection;
}

UnoUrlDescriptor const & UnoUrl::getProtocol() const
{
    return m_xImpl->m_aProtocol;
}

rtl::OUString const & UnoUrl::getObjectName() const
{
    return m_xImpl->m_aObjectName;
}
<commit_msg>INTEGRATION: CWS ooo20031216 (1.1.76); FILE MERGED 2003/12/23 10:55:35 waratah 1.1.76.1: #i1858#  add default to initialise a potentially unitialised variable<commit_after>/*************************************************************************
 *
 *  $RCSfile: unourl.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2004-02-04 11:55:42 $
 *
 *  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: 2002 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "cppuhelper/unourl.hxx"

#include "osl/diagnose.h"
#include "rtl/malformeduriexception.hxx"
#include "rtl/string.h"
#include "rtl/textenc.h"
#include "rtl/uri.h"
#include "rtl/uri.hxx"
#include "rtl/ustring.h"
#include "rtl/ustring.hxx"
#include "sal/types.h"

#include <map>

using cppu::UnoUrl;
using cppu::UnoUrlDescriptor;

namespace {

inline bool isAlphanum(sal_Unicode c)
{
    return c >= 0x30 && c <= 0x39 // '0'--'9'
        || c >= 0x41 && c <= 0x5A // 'A'--'Z'
        || c >= 0x61 && c <= 0x7A; // 'a'--'z'
}

}

class UnoUrlDescriptor::Impl
{
public:
    typedef std::map< rtl::OUString, rtl::OUString > Parameters;

    rtl::OUString m_aDescriptor;
    rtl::OUString m_aName;
    Parameters m_aParameters;

    /** @exception rtl::MalformedUriException
     */
    explicit inline Impl(rtl::OUString const & m_aDescriptor);

    inline Impl * clone() const { return new Impl(*this); }
};

inline UnoUrlDescriptor::Impl::Impl(rtl::OUString const & rDescriptor)
{
    m_aDescriptor = rDescriptor;
    enum State { STATE_NAME0, STATE_NAME, STATE_KEY0, STATE_KEY, STATE_VALUE };
    State eState = STATE_NAME0;
    sal_Int32 nStart = 0;
    rtl::OUString aKey;
    for (sal_Int32 i = 0;; ++i)
    {
        bool bEnd = i == rDescriptor.getLength();
        sal_Unicode c = bEnd ? 0 : rDescriptor.getStr()[i];
        switch (eState)
        {
        case STATE_NAME0:
            if (bEnd || !isAlphanum(c))
                throw rtl::MalformedUriException(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                      "UNO URL contains bad descriptor name")));
            nStart = i;
            eState = STATE_NAME;
            break;

        case STATE_NAME:
            if (bEnd || c == 0x2C) // ','
            {
                m_aName
                    = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
                eState = STATE_KEY0;
            }
            else if (!isAlphanum(c))
                throw rtl::MalformedUriException(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                      "UNO URL contains bad descriptor name")));
            break;

        case STATE_KEY0:
            if (bEnd || !isAlphanum(c))
                throw rtl::MalformedUriException(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                      "UNO URL contains bad parameter key")));
            nStart = i;
            eState = STATE_KEY;
            break;

        case STATE_KEY:
            if (c == 0x3D) // '='
            {
                aKey = rDescriptor.copy(nStart, i - nStart).toAsciiLowerCase();
                nStart = i + 1;
                eState = STATE_VALUE;
            }
            else if (bEnd || !isAlphanum(c))
                throw rtl::MalformedUriException(
                    rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                      "UNO URL contains bad parameter key")));
            break;

        case STATE_VALUE:
            if (bEnd || c == 0x2C) // ','
            {
                if (!m_aParameters.insert(
                        Parameters::value_type(
                            aKey,
                            rtl::Uri::decode(rDescriptor.copy(nStart,
                                                              i - nStart),
                                             rtl_UriDecodeWithCharset,
                                             RTL_TEXTENCODING_UTF8))).second)
                    throw rtl::MalformedUriException(
                        rtl::OUString(
                            RTL_CONSTASCII_USTRINGPARAM(
                                "UNO URL contains duplicated parameter")));
                eState = STATE_KEY0;
            }
            break;
        }
        if (bEnd)
            break;
    }
}

UnoUrlDescriptor::UnoUrlDescriptor(rtl::OUString const & rDescriptor):
    m_xImpl(new Impl(rDescriptor))
{}

UnoUrlDescriptor::UnoUrlDescriptor(std::auto_ptr< Impl > & rImpl):
    m_xImpl(rImpl)
{}

UnoUrlDescriptor::UnoUrlDescriptor(UnoUrlDescriptor const & rOther):
    m_xImpl(rOther.m_xImpl->clone())
{}

UnoUrlDescriptor::~UnoUrlDescriptor()
{}

UnoUrlDescriptor & UnoUrlDescriptor::operator =(UnoUrlDescriptor const & rOther)
{
    m_xImpl.reset(rOther.m_xImpl->clone());
    return *this;
}

rtl::OUString const & UnoUrlDescriptor::getDescriptor() const
{
    return m_xImpl->m_aDescriptor;
}

rtl::OUString const & UnoUrlDescriptor::getName() const
{
    return m_xImpl->m_aName;
}

bool UnoUrlDescriptor::hasParameter(rtl::OUString const & rKey) const
{
    return m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase())
        != m_xImpl->m_aParameters.end();
}

rtl::OUString UnoUrlDescriptor::getParameter(rtl::OUString const & rKey) const
{
    Impl::Parameters::const_iterator
        aIt(m_xImpl->m_aParameters.find(rKey.toAsciiLowerCase()));
    return aIt == m_xImpl->m_aParameters.end() ? rtl::OUString() : aIt->second;
}

class UnoUrl::Impl
{
public:
    UnoUrlDescriptor m_aConnection;
    UnoUrlDescriptor m_aProtocol;
    rtl::OUString m_aObjectName;

    inline Impl * clone() const { return new Impl(*this); }

    /** @exception rtl::MalformedUriException
     */
    static inline Impl * create(rtl::OUString const & rUrl);

private:
    inline Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection,
                std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol,
                rtl::OUString const & rObjectName);
};

inline UnoUrl::Impl::Impl(std::auto_ptr< UnoUrlDescriptor::Impl > & rConnection,
                          std::auto_ptr< UnoUrlDescriptor::Impl > & rProtocol,
                          rtl::OUString const & rObjectName):
    m_aConnection(rConnection),
    m_aProtocol(rProtocol),
    m_aObjectName(rObjectName)
{}

inline UnoUrl::Impl * UnoUrl::Impl::create(rtl::OUString const & rUrl)
{
    if (!rUrl.matchIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("uno:"), 0))
        throw rtl::MalformedUriException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                              "UNO URL does not start with \"uno:\"")));
    sal_Int32 i = RTL_CONSTASCII_LENGTH("uno:");
    sal_Int32 j = rUrl.indexOf(';', i);
    if (j < 0)
        throw rtl::MalformedUriException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                              "UNO URL has too few semicolons")));
    std::auto_ptr< UnoUrlDescriptor::Impl >
        xConnection(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i)));
    i = j + 1;
    j = rUrl.indexOf(0x3B, i); // ';'
    if (j < 0)
        throw rtl::MalformedUriException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                              "UNO URL has too few semicolons")));
    std::auto_ptr< UnoUrlDescriptor::Impl >
        xProtocol(new UnoUrlDescriptor::Impl(rUrl.copy(i, j - i)));
    i = j + 1;
    if (i == rUrl.getLength())
        throw rtl::MalformedUriException(
            rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                              "UNO URL contains empty ObjectName")));
    for (j = i; j < rUrl.getLength(); ++j)
    {
        sal_Unicode c = rUrl.getStr()[j];
        if (!isAlphanum(c) && c != 0x21 && c != 0x24 // '!', '$'
            && c != 0x26 && c != 0x27 && c != 0x28 // '&', ''', '('
            && c != 0x28 && c != 0x2A && c != 0x2B // ')', '*', '+'
            && c != 0x2C && c != 0x2D && c != 0x2E // ',', '-', '.'
            && c != 0x2F && c != 0x3A && c != 0x3D // '/', ':', '='
            && c != 0x3F && c != 0x40 && c != 0x5F // '?', '@', '_'
            && c != 0x7E) // '~'
            throw rtl::MalformedUriException(
                rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
                                  "UNO URL contains invalid ObjectName")));
    }
    return new Impl(xConnection, xProtocol, rUrl.copy(i));
}

UnoUrl::UnoUrl(rtl::OUString const & rUrl): m_xImpl(Impl::create(rUrl))
{}

UnoUrl::UnoUrl(UnoUrl const & rOther): m_xImpl(rOther.m_xImpl->clone())
{}

UnoUrl::~UnoUrl()
{}

UnoUrl & UnoUrl::operator =(UnoUrl const & rOther)
{
    m_xImpl.reset(rOther.m_xImpl->clone());
    return *this;
}

UnoUrlDescriptor const & UnoUrl::getConnection() const
{
    return m_xImpl->m_aConnection;
}

UnoUrlDescriptor const & UnoUrl::getProtocol() const
{
    return m_xImpl->m_aProtocol;
}

rtl::OUString const & UnoUrl::getObjectName() const
{
    return m_xImpl->m_aObjectName;
}
<|endoftext|>