<commit_before>//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the X86 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "X86Subtarget.h"
#include "X86GenSubtarget.inc"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include <iostream>
using namespace llvm;

cl::opt<X86Subtarget::AsmWriterFlavorTy>
AsmWriterFlavor("x86-asm-syntax", cl::init(X86Subtarget::unset),
  cl::desc("Choose style of code to emit from X86 backend:"),
  cl::values(
    clEnumValN(X86Subtarget::att,   "att",   "  Emit AT&T-style assembly"),
    clEnumValN(X86Subtarget::intel, "intel", "  Emit Intel-style assembly"),
    clEnumValEnd));

/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
/// specified arguments.  If we can't run cpuid on the host, return true.
bool X86::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
                          unsigned *rECX, unsigned *rEDX) {
#if defined(__x86_64__)
  // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
  asm ("movq\t%%rbx, %%rsi\n\t"
       "cpuid\n\t"
       "xchgq\t%%rbx, %%rsi\n\t"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
#if defined(__GNUC__)
  asm ("movl\t%%ebx, %%esi\n\t"
       "cpuid\n\t"
       "xchgl\t%%ebx, %%esi\n\t"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(_MSC_VER)
  __asm {
    mov   eax,value
    cpuid
    mov   esi,rEAX
    mov   dword ptr [esi],eax
    mov   esi,rEBX
    mov   dword ptr [esi],ebx
    mov   esi,rECX
    mov   dword ptr [esi],ecx
    mov   esi,rEDX
    mov   dword ptr [esi],edx
  }
  return false;
#endif
#endif
  return true;
}

void X86Subtarget::AutoDetectSubtargetFeatures() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  union {
    unsigned u[3];
    char     c[12];
  } text;

  if (X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
    return;

  // FIXME: support for AMD family of processors.
  if (memcmp(text.c, "GenuineIntel", 12) == 0) {
    X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);

    if ((EDX >> 23) & 0x1) X86SSELevel = MMX;
    if ((EDX >> 25) & 0x1) X86SSELevel = SSE1;
    if ((EDX >> 26) & 0x1) X86SSELevel = SSE2;
    if (ECX & 0x1)         X86SSELevel = SSE3;

    X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
    HasX86_64 = (EDX >> 29) & 0x1;
  }
}

static const char *GetCurrentX86CPU() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  if (X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
    return "generic";
  unsigned Family  = (EAX >> 8) & 0xf; // Bits 8 - 11
  unsigned Model   = (EAX >> 4) & 0xf; // Bits 4 - 7
  X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
  bool Em64T = (EDX >> 29) & 0x1;

  union {
    unsigned u[3];
    char     c[12];
  } text;

  X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
  if (memcmp(text.c, "GenuineIntel", 12) == 0) {
    switch (Family) {
      case 3:
        return "i386";
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 4:  return "pentium-mmx";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 1:  return "pentiumpro";
        case 3:
        case 5:
        case 6:  return "pentium2";
        case 7:
        case 8:
        case 10:
        case 11: return "pentium3";
        case 9:
        case 13: return "pentium-m";
        case 14: return "yonah";
        case 15: return "core2";
        default: return "i686";
        }
      case 15: {
        switch (Model) {
        case 3:
        case 4:
          return (Em64T) ? "nocona" : "prescott";
        default:
          return (Em64T) ? "x86-64" : "pentium4";
        }
      }

    default:
      return "generic";
    }
  } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
    // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
    // appears to be no way to generate the wide variety of AMD-specific targets
    // from the information returned from CPUID.
    switch (Family) {
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 6:
        case 7:  return "k6";
        case 8:  return "k6-2";
        case 9:
        case 13: return "k6-3";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 4:  return "athlon-tbird";
        case 6:
        case 7:
        case 8:  return "athlon-mp";
        case 10: return "athlon-xp";
        default: return "athlon";
        }
      case 15:
        switch (Model) {
        case 5:  return "athlon-fx"; // also opteron
        default: return "athlon64";
        }

    default:
      return "generic";
    }
  } else {
    return "generic";
  }
}

X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit)
  : AsmFlavor(AsmWriterFlavor)
  , X86SSELevel(NoMMXSSE)
  , HasX86_64(false)
  , stackAlignment(8)
  // FIXME: this is a known good value for Yonah. How about others?
  , MinRepStrSizeThreshold(128)
  , Is64Bit(is64Bit)
  , TargetType(isELF) { // Default to ELF unless otherwise specified.

  // Determine default and user specified characteristics
  if (!FS.empty()) {
    // If feature string is not empty, parse features string.
    std::string CPU = GetCurrentX86CPU();
    ParseSubtargetFeatures(FS, CPU);

    if (Is64Bit && !HasX86_64)
      std::cerr << "Warning: Generation of 64-bit code for a 32-bit processor "
                   "requested.\n";
    if (Is64Bit && X86SSELevel < SSE2)
      std::cerr << "Warning: 64-bit processors all have at least SSE2.\n";
  } else {
    // Otherwise, use CPUID to auto-detect feature set.
    AutoDetectSubtargetFeatures();
  }

  // If requesting codegen for X86-64, make sure that 64-bit and SSE2 features
  // are enabled.  These are available on all x86-64 CPUs.
  if (Is64Bit) {
    HasX86_64 = true;
    if (X86SSELevel < SSE2)
      X86SSELevel = SSE2;
  }

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    if (TT.find("cygwin") != std::string::npos ||
        TT.find("mingw")  != std::string::npos)
      TargetType = isCygwin;
    else if (TT.find("darwin") != std::string::npos)
      TargetType = isDarwin;
    else if (TT.find("win32") != std::string::npos)
      TargetType = isWindows;
  } else if (TT.empty()) {
#if defined(__CYGWIN__) || defined(__MINGW32__)
    TargetType = isCygwin;
#elif defined(__APPLE__)
    TargetType = isDarwin;
#elif defined(_WIN32)
    TargetType = isWindows;
#endif
  }

  // If the asm syntax hasn't been overridden on the command line, use whatever
  // the target wants.
  if (AsmFlavor == X86Subtarget::unset) {
    if (TargetType == isWindows) {
      AsmFlavor = X86Subtarget::intel;
    } else {
      AsmFlavor = X86Subtarget::att;
    }
  }

  if (TargetType == isDarwin || TargetType == isCygwin)
    stackAlignment = 16;
}
<commit_msg>16-byte stack alignment for X86-64 ELF. Patch by Dan Gohman.<commit_after>//===-- X86Subtarget.cpp - X86 Subtarget Information ------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Nate Begeman and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the X86 specific subclass of TargetSubtarget.
//
//===----------------------------------------------------------------------===//

#include "X86Subtarget.h"
#include "X86GenSubtarget.inc"
#include "llvm/Module.h"
#include "llvm/Support/CommandLine.h"
#include <iostream>
using namespace llvm;

cl::opt<X86Subtarget::AsmWriterFlavorTy>
AsmWriterFlavor("x86-asm-syntax", cl::init(X86Subtarget::unset),
  cl::desc("Choose style of code to emit from X86 backend:"),
  cl::values(
    clEnumValN(X86Subtarget::att,   "att",   "  Emit AT&T-style assembly"),
    clEnumValN(X86Subtarget::intel, "intel", "  Emit Intel-style assembly"),
    clEnumValEnd));

/// GetCpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
/// specified arguments.  If we can't run cpuid on the host, return true.
bool X86::GetCpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
                          unsigned *rECX, unsigned *rEDX) {
#if defined(__x86_64__)
  // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
  asm ("movq\t%%rbx, %%rsi\n\t"
       "cpuid\n\t"
       "xchgq\t%%rbx, %%rsi\n\t"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
#if defined(__GNUC__)
  asm ("movl\t%%ebx, %%esi\n\t"
       "cpuid\n\t"
       "xchgl\t%%ebx, %%esi\n\t"
       : "=a" (*rEAX),
         "=S" (*rEBX),
         "=c" (*rECX),
         "=d" (*rEDX)
       :  "a" (value));
  return false;
#elif defined(_MSC_VER)
  __asm {
    mov   eax,value
    cpuid
    mov   esi,rEAX
    mov   dword ptr [esi],eax
    mov   esi,rEBX
    mov   dword ptr [esi],ebx
    mov   esi,rECX
    mov   dword ptr [esi],ecx
    mov   esi,rEDX
    mov   dword ptr [esi],edx
  }
  return false;
#endif
#endif
  return true;
}

void X86Subtarget::AutoDetectSubtargetFeatures() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  union {
    unsigned u[3];
    char     c[12];
  } text;

  if (X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1))
    return;

  // FIXME: support for AMD family of processors.
  if (memcmp(text.c, "GenuineIntel", 12) == 0) {
    X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX);

    if ((EDX >> 23) & 0x1) X86SSELevel = MMX;
    if ((EDX >> 25) & 0x1) X86SSELevel = SSE1;
    if ((EDX >> 26) & 0x1) X86SSELevel = SSE2;
    if (ECX & 0x1)         X86SSELevel = SSE3;

    X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
    HasX86_64 = (EDX >> 29) & 0x1;
  }
}

static const char *GetCurrentX86CPU() {
  unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
  if (X86::GetCpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
    return "generic";
  unsigned Family  = (EAX >> 8) & 0xf; // Bits 8 - 11
  unsigned Model   = (EAX >> 4) & 0xf; // Bits 4 - 7
  X86::GetCpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
  bool Em64T = (EDX >> 29) & 0x1;

  union {
    unsigned u[3];
    char     c[12];
  } text;

  X86::GetCpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
  if (memcmp(text.c, "GenuineIntel", 12) == 0) {
    switch (Family) {
      case 3:
        return "i386";
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 4:  return "pentium-mmx";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 1:  return "pentiumpro";
        case 3:
        case 5:
        case 6:  return "pentium2";
        case 7:
        case 8:
        case 10:
        case 11: return "pentium3";
        case 9:
        case 13: return "pentium-m";
        case 14: return "yonah";
        case 15: return "core2";
        default: return "i686";
        }
      case 15: {
        switch (Model) {
        case 3:
        case 4:
          return (Em64T) ? "nocona" : "prescott";
        default:
          return (Em64T) ? "x86-64" : "pentium4";
        }
      }

    default:
      return "generic";
    }
  } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
    // FIXME: this poorly matches the generated SubtargetFeatureKV table.  There
    // appears to be no way to generate the wide variety of AMD-specific targets
    // from the information returned from CPUID.
    switch (Family) {
      case 4:
        return "i486";
      case 5:
        switch (Model) {
        case 6:
        case 7:  return "k6";
        case 8:  return "k6-2";
        case 9:
        case 13: return "k6-3";
        default: return "pentium";
        }
      case 6:
        switch (Model) {
        case 4:  return "athlon-tbird";
        case 6:
        case 7:
        case 8:  return "athlon-mp";
        case 10: return "athlon-xp";
        default: return "athlon";
        }
      case 15:
        switch (Model) {
        case 5:  return "athlon-fx"; // also opteron
        default: return "athlon64";
        }

    default:
      return "generic";
    }
  } else {
    return "generic";
  }
}

X86Subtarget::X86Subtarget(const Module &M, const std::string &FS, bool is64Bit)
  : AsmFlavor(AsmWriterFlavor)
  , X86SSELevel(NoMMXSSE)
  , HasX86_64(false)
  , stackAlignment(8)
  // FIXME: this is a known good value for Yonah. How about others?
  , MinRepStrSizeThreshold(128)
  , Is64Bit(is64Bit)
  , TargetType(isELF) { // Default to ELF unless otherwise specified.

  // Determine default and user specified characteristics
  if (!FS.empty()) {
    // If feature string is not empty, parse features string.
    std::string CPU = GetCurrentX86CPU();
    ParseSubtargetFeatures(FS, CPU);

    if (Is64Bit && !HasX86_64)
      std::cerr << "Warning: Generation of 64-bit code for a 32-bit processor "
                   "requested.\n";
    if (Is64Bit && X86SSELevel < SSE2)
      std::cerr << "Warning: 64-bit processors all have at least SSE2.\n";
  } else {
    // Otherwise, use CPUID to auto-detect feature set.
    AutoDetectSubtargetFeatures();
  }

  // If requesting codegen for X86-64, make sure that 64-bit and SSE2 features
  // are enabled.  These are available on all x86-64 CPUs.
  if (Is64Bit) {
    HasX86_64 = true;
    if (X86SSELevel < SSE2)
      X86SSELevel = SSE2;
  }

  // Set the boolean corresponding to the current target triple, or the default
  // if one cannot be determined, to true.
  const std::string& TT = M.getTargetTriple();
  if (TT.length() > 5) {
    if (TT.find("cygwin") != std::string::npos ||
        TT.find("mingw")  != std::string::npos)
      TargetType = isCygwin;
    else if (TT.find("darwin") != std::string::npos)
      TargetType = isDarwin;
    else if (TT.find("win32") != std::string::npos)
      TargetType = isWindows;
  } else if (TT.empty()) {
#if defined(__CYGWIN__) || defined(__MINGW32__)
    TargetType = isCygwin;
#elif defined(__APPLE__)
    TargetType = isDarwin;
#elif defined(_WIN32)
    TargetType = isWindows;
#endif
  }

  // If the asm syntax hasn't been overridden on the command line, use whatever
  // the target wants.
  if (AsmFlavor == X86Subtarget::unset) {
    if (TargetType == isWindows) {
      AsmFlavor = X86Subtarget::intel;
    } else {
      AsmFlavor = X86Subtarget::att;
    }
  }

  if (TargetType == isDarwin ||
      TargetType == isCygwin ||
      (TargetType == isELF && Is64Bit))
    stackAlignment = 16;
}
<|endoftext|>


<commit_before>#ifndef __MAPNIK_VECTOR_TILE_LOAD_TILE_H__
#define __MAPNIK_VECTOR_TILE_LOAD_TILE_H__

// mapnik-vector-tile
#include "vector_tile_config.hpp"
#include "vector_tile_compression.hpp"
#include "vector_tile_tile.hpp"
#include "vector_tile_datasource_pbf.hpp"
#include "vector_tile_is_valid.hpp"

// mapnik
#include <mapnik/map.hpp>
#include <mapnik/layer.hpp>

//protozero
#include <protozero/pbf_reader.hpp>
#include <protozero/pbf_writer.hpp>

// std
#include <set>
#include <string>

namespace mapnik
{

namespace vector_tile_impl
{

void merge_from_buffer(merc_tile & t, const char * data, std::size_t size)
{
    using ds_ptr = std::shared_ptr<mapnik::vector_tile_impl::tile_datasource_pbf>;
    protozero::pbf_reader tile_msg(data, size);
    std::vector<ds_ptr> ds_vec;
    while (tile_msg.next())
    {
        switch (tile_msg.tag())
        {
            case Tile_Encoding::LAYERS:
                {
                    auto layer_data = tile_msg.get_data();
                    protozero::pbf_reader layer_valid_msg(layer_data);
                    std::set<validity_error> errors;
                    std::string layer_name;
                    std::uint32_t version = 1;
                    layer_is_valid(layer_valid_msg, errors, layer_name, version);
                    if (!errors.empty())
                    {
                        std::string layer_errors;
                        validity_error_to_string(errors, layer_errors);
                        throw std::runtime_error(layer_errors);
                    }
                    if (t.has_layer(layer_name))
                    {
                        continue;
                    }
                    if (version == 1)
                    {
                        // v1 tiles will be convereted to v2
                        protozero::pbf_reader layer_msg(layer_data);
                        ds_vec.push_back(std::make_shared<mapnik::vector_tile_impl::tile_datasource_pbf>(
                                    layer_msg,
                                    t.x(),
                                    t.y(),
                                    t.z(),
                                    true));
                    }
                    else
                    {
                        t.append_layer_buffer(layer_data.first, layer_data.second, layer_name);
                    }
                }
                break;
            default:
                throw std::runtime_error("Vector Tile Buffer contains invalid tag");
                break;
        }
    }
    if (ds_vec.empty())
    {
        return;
    }
    // Convert v1 tiles to v2
    std::int32_t prev_buffer_size = t.buffer_size();
    t.buffer_size(4096); // very large buffer so we don't miss any buffered points
    mapnik::Map map(t.tile_size(), t.tile_size(), "+init=epsg:3857");
    for (auto ds : ds_vec)
    {
        ds->set_envelope(t.get_buffered_extent());
        mapnik::layer lyr(ds->get_name(), "+init=epsg:3857");
        lyr.set_datasource(ds);
        map.add_layer(lyr);
    }
    mapnik::vector_tile_impl::processor ren(map);
    ren.set_multi_polygon_union(true);
    ren.set_fill_type(mapnik::vector_tile_impl::even_odd_fill);
    ren.set_process_all_rings(true);
    //ren.set_simplify_distance(4.0);
    ren.update_tile(t);
    t.buffer_size(prev_buffer_size);
}

void merge_from_compressed_buffer(merc_tile & t, const char * data, std::size_t size)
{
    if (mapnik::vector_tile_impl::is_gzip_compressed(data,size) ||
        mapnik::vector_tile_impl::is_zlib_compressed(data,size))
    {
        std::string decompressed;
        mapnik::vector_tile_impl::zlib_decompress(data, size, decompressed);
        return merge_from_buffer(t, decompressed.data(), decompressed.size());
    }
    else
    {
        return merge_from_buffer(t, data, size);
    }
}

void add_image_buffer_as_tile_layer(merc_tile & t, std::string const& layer_name, const char * data, std::size_t size)
{
    std::string layer_buffer;
    protozero::pbf_writer layer_writer(layer_buffer);
    layer_writer.add_uint32(Layer_Encoding::VERSION, 2);
    layer_writer.add_string(Layer_Encoding::NAME, layer_name);
    layer_writer.add_uint32(Layer_Encoding::EXTENT, 4096);
    {
        protozero::pbf_writer feature_writer(layer_writer, Layer_Encoding::FEATURES);
        feature_writer.add_bytes(Feature_Encoding::RASTER, data, size);
    }
    t.append_layer_buffer(layer_buffer.data(), layer_buffer.size(), layer_name);
}

} // end ns vector_tile_impl

} // end ns mapnik

#endif // __MAPNIK_VECTOR_TILE_LOAD_TILE_H__
<commit_msg>fix spelling in code comment<commit_after>#ifndef __MAPNIK_VECTOR_TILE_LOAD_TILE_H__
#define __MAPNIK_VECTOR_TILE_LOAD_TILE_H__

// mapnik-vector-tile
#include "vector_tile_config.hpp"
#include "vector_tile_compression.hpp"
#include "vector_tile_tile.hpp"
#include "vector_tile_datasource_pbf.hpp"
#include "vector_tile_is_valid.hpp"

// mapnik
#include <mapnik/map.hpp>
#include <mapnik/layer.hpp>

//protozero
#include <protozero/pbf_reader.hpp>
#include <protozero/pbf_writer.hpp>

// std
#include <set>
#include <string>

namespace mapnik
{

namespace vector_tile_impl
{

void merge_from_buffer(merc_tile & t, const char * data, std::size_t size)
{
    using ds_ptr = std::shared_ptr<mapnik::vector_tile_impl::tile_datasource_pbf>;
    protozero::pbf_reader tile_msg(data, size);
    std::vector<ds_ptr> ds_vec;
    while (tile_msg.next())
    {
        switch (tile_msg.tag())
        {
            case Tile_Encoding::LAYERS:
                {
                    auto layer_data = tile_msg.get_data();
                    protozero::pbf_reader layer_valid_msg(layer_data);
                    std::set<validity_error> errors;
                    std::string layer_name;
                    std::uint32_t version = 1;
                    layer_is_valid(layer_valid_msg, errors, layer_name, version);
                    if (!errors.empty())
                    {
                        std::string layer_errors;
                        validity_error_to_string(errors, layer_errors);
                        throw std::runtime_error(layer_errors);
                    }
                    if (t.has_layer(layer_name))
                    {
                        continue;
                    }
                    if (version == 1)
                    {
                        // v1 tiles will be converted to v2
                        protozero::pbf_reader layer_msg(layer_data);
                        ds_vec.push_back(std::make_shared<mapnik::vector_tile_impl::tile_datasource_pbf>(
                                    layer_msg,
                                    t.x(),
                                    t.y(),
                                    t.z(),
                                    true));
                    }
                    else
                    {
                        t.append_layer_buffer(layer_data.first, layer_data.second, layer_name);
                    }
                }
                break;
            default:
                throw std::runtime_error("Vector Tile Buffer contains invalid tag");
                break;
        }
    }
    if (ds_vec.empty())
    {
        return;
    }
    // Convert v1 tiles to v2
    std::int32_t prev_buffer_size = t.buffer_size();
    t.buffer_size(4096); // very large buffer so we don't miss any buffered points
    mapnik::Map map(t.tile_size(), t.tile_size(), "+init=epsg:3857");
    for (auto ds : ds_vec)
    {
        ds->set_envelope(t.get_buffered_extent());
        mapnik::layer lyr(ds->get_name(), "+init=epsg:3857");
        lyr.set_datasource(ds);
        map.add_layer(lyr);
    }
    mapnik::vector_tile_impl::processor ren(map);
    ren.set_multi_polygon_union(true);
    ren.set_fill_type(mapnik::vector_tile_impl::even_odd_fill);
    ren.set_process_all_rings(true);
    //ren.set_simplify_distance(4.0);
    ren.update_tile(t);
    t.buffer_size(prev_buffer_size);
}

void merge_from_compressed_buffer(merc_tile & t, const char * data, std::size_t size)
{
    if (mapnik::vector_tile_impl::is_gzip_compressed(data,size) ||
        mapnik::vector_tile_impl::is_zlib_compressed(data,size))
    {
        std::string decompressed;
        mapnik::vector_tile_impl::zlib_decompress(data, size, decompressed);
        return merge_from_buffer(t, decompressed.data(), decompressed.size());
    }
    else
    {
        return merge_from_buffer(t, data, size);
    }
}

void add_image_buffer_as_tile_layer(merc_tile & t, std::string const& layer_name, const char * data, std::size_t size)
{
    std::string layer_buffer;
    protozero::pbf_writer layer_writer(layer_buffer);
    layer_writer.add_uint32(Layer_Encoding::VERSION, 2);
    layer_writer.add_string(Layer_Encoding::NAME, layer_name);
    layer_writer.add_uint32(Layer_Encoding::EXTENT, 4096);
    {
        protozero::pbf_writer feature_writer(layer_writer, Layer_Encoding::FEATURES);
        feature_writer.add_bytes(Feature_Encoding::RASTER, data, size);
    }
    t.append_layer_buffer(layer_buffer.data(), layer_buffer.size(), layer_name);
}

} // end ns vector_tile_impl

} // end ns mapnik

#endif // __MAPNIK_VECTOR_TILE_LOAD_TILE_H__
<|endoftext|>


<commit_before>//===- unittest/Format/FormatTestProto.cpp --------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "FormatTestUtils.h"
#include "clang/Format/Format.h"
#include "llvm/Support/Debug.h"
#include "gtest/gtest.h"

#define DEBUG_TYPE "format-test"

namespace clang {
namespace format {

class FormatTestProto : public ::testing::Test {
protected:
  static std::string format(llvm::StringRef Code, unsigned Offset,
                            unsigned Length, const FormatStyle &Style) {
    DEBUG(llvm::errs() << "---\n");
    DEBUG(llvm::errs() << Code << "\n\n");
    std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
    tooling::Replacements Replaces = reformat(Style, Code, Ranges);
    auto Result = applyAllReplacements(Code, Replaces);
    EXPECT_TRUE(static_cast<bool>(Result));
    DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
    return *Result;
  }

  static std::string format(llvm::StringRef Code) {
    FormatStyle Style = getGoogleStyle(FormatStyle::LK_Proto);
    Style.ColumnLimit = 60; // To make writing tests easier.
    return format(Code, 0, Code.size(), Style);
  }

  static void verifyFormat(llvm::StringRef Code) {
    EXPECT_EQ(Code.str(), format(test::messUp(Code)));
  }
};

TEST_F(FormatTestProto, FormatsMessages) {
  verifyFormat("message SomeMessage {\n"
               "  required int32 field1 = 1;\n"
               "}");
  verifyFormat("message SomeMessage {\n"
               "  required .absolute.Reference field1 = 1;\n"
               "}");
  verifyFormat("message SomeMessage {\n"
               "  required int32 field1 = 1;\n"
               "  optional string field2 = 2 [default = \"2\"]\n"
               "}");

  verifyFormat("message SomeMessage {\n"
               "  optional really.really.long.qualified.type.aaa.aaaaaaa\n"
               "      fiiiiiiiiiiiiiiiiiiiiiiiiield = 1;\n"
               "  optional\n"
               "      really.really.long.qualified.type.aaa.aaaaaaa.aaaaaaaa\n"
               "          another_fiiiiiiiiiiiiiiiiiiiiield = 2;\n"
               "}");
}

TEST_F(FormatTestProto, KeywordsInOtherLanguages) {
  verifyFormat("optional string operator = 1;");
}

TEST_F(FormatTestProto, FormatsEnums) {
  verifyFormat("enum Type {\n"
               "  UNKNOWN = 0;\n"
               "  TYPE_A = 1;\n"
               "  TYPE_B = 2;\n"
               "};");
  verifyFormat("enum Type {\n"
               "  UNKNOWN = 0 [(some_options) = {a: aa, b: bb}];\n"
               "};");
  verifyFormat("enum Type {\n"
               "  UNKNOWN = 0 [(some_options) = {\n"
               "    a: aa,  // wrap\n"
               "    b: bb\n"
               "  }];\n"
               "};");
}

TEST_F(FormatTestProto, UnderstandsReturns) {
  verifyFormat("rpc Search(SearchRequest) returns (SearchResponse);");
}

TEST_F(FormatTestProto, MessageFieldAttributes) {
  verifyFormat("optional string test = 1 [default = \"test\"];");
  verifyFormat("optional bool a = 1 [default = true, deprecated = true];");
  verifyFormat("optional LongMessageType long_proto_field = 1 [\n"
               "  default = REALLY_REALLY_LONG_CONSTANT_VALUE,\n"
               "  deprecated = true\n"
               "];");
  verifyFormat("optional LongMessageType long_proto_field = 1\n"
               "    [default = REALLY_REALLY_LONG_CONSTANT_VALUE];");
  verifyFormat("repeated double value = 1\n"
               "    [(aaaaaaa.aaaaaaaaa) = {aaaaaaaaaaaaaaaaa: AAAAAAAA}];");
  verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
               "  aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n"
               "  bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
               "}];");
  verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
               "  aaaaaaaaaaaaaaaa: AAAAAAAAAA\n"
               "  bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
               "}];");
  verifyFormat("repeated double value = 1 [\n"
               "  (aaaaaaa.aaaaaaaaa) = {\n"
               "    aaaaaaaaaaaaaaaa: AAAAAAAAAA\n"
               "    bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
               "  },\n"
               "  (bbbbbbb.bbbbbbbbb) = {\n"
               "    aaaaaaaaaaaaaaaa: AAAAAAAAAA\n"
               "    bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
               "  }\n"
               "];");
  verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
               "  type: \"AAAAAAAAAA\"\n"
               "  is: \"AAAAAAAAAA\"\n"
               "  or: \"BBBBBBBBBB\"\n"
               "}];");
  verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
               "  aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n"
               "  bbbbbbb: BBBB,\n"
               "  bbbb: BBB\n"
               "}];");
  verifyFormat("optional AAA aaa = 1 [\n"
               "  foo = {\n"
               "    key: 'a'  //\n"
               "  },\n"
               "  bar = {\n"
               "    key: 'a'  //\n"
               "  }\n"
               "];");
  verifyFormat("optional string test = 1 [default =\n"
               "                              \"test\"\n"
               "                              \"test\"];");
  verifyFormat("optional Aaaaaaaa aaaaaaaa = 12 [\n"
               "  (aaa) = aaaa,\n"
               "  (bbbbbbbbbbbbbbbbbbbbbbbbbb) = {\n"
               "    aaaaaaaaaaaaaaaaa: true,\n"
               "    aaaaaaaaaaaaaaaa: true\n"
               "  }\n"
               "];");
}

TEST_F(FormatTestProto, DoesntWrapFileOptions) {
  EXPECT_EQ(
      "option java_package = "
      "\"some.really.long.package.that.exceeds.the.column.limit\";",
      format("option    java_package   =    "
             "\"some.really.long.package.that.exceeds.the.column.limit\";"));
}

TEST_F(FormatTestProto, FormatsOptions) {
  verifyFormat("option (MyProto.options) = {\n"
               "  field_a: OK\n"
               "  field_b: \"OK\"\n"
               "  field_c: \"OK\"\n"
               "  msg_field: {field_d: 123}\n"
               "};");
  verifyFormat("option (MyProto.options) = {\n"
               "  field_a: OK\n"
               "  field_b: \"OK\"\n"
               "  field_c: \"OK\"\n"
               "  msg_field: {field_d: 123 field_e: OK}\n"
               "};");
  verifyFormat("option (MyProto.options) = {\n"
               "  field_a: OK  // Comment\n"
               "  field_b: \"OK\"\n"
               "  field_c: \"OK\"\n"
               "  msg_field: {field_d: 123}\n"
               "};");
  verifyFormat("option (MyProto.options) = {\n"
               "  field_c: \"OK\"\n"
               "  msg_field{field_d: 123}\n"
               "};");

  // Support syntax with <> instead of {}.
  verifyFormat("option (MyProto.options) = {\n"
               "  field_c: \"OK\",\n"
               "  msg_field: <field_d: 123>\n"
               "};");
}

TEST_F(FormatTestProto, FormatsService) {
  verifyFormat("service SearchService {\n"
               "  rpc Search(SearchRequest) returns (SearchResponse) {\n"
               "    option foo = true;\n"
               "  }\n"
               "};");
}

TEST_F(FormatTestProto, ExtendingMessage) {
  verifyFormat("extend .foo.Bar {\n"
               "}");
}

TEST_F(FormatTestProto, FormatsImports) {
  verifyFormat("import \"a.proto\";\n"
               "import \"b.proto\";\n"
               "// comment\n"
               "message A {\n"
               "}");

  verifyFormat("import public \"a.proto\";\n"
               "import \"b.proto\";\n"
               "// comment\n"
               "message A {\n"
               "}");

  // Missing semicolons should not confuse clang-format.
  verifyFormat("import \"a.proto\"\n"
               "import \"b.proto\"\n"
               "// comment\n"
               "message A {\n"
               "}");
}

} // end namespace tooling
} // end namespace clang
<commit_msg>[clang-format] Add a test for associative map proto buffer fields<commit_after>//===- unittest/Format/FormatTestProto.cpp --------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "FormatTestUtils.h"
#include "clang/Format/Format.h"
#include "llvm/Support/Debug.h"
#include "gtest/gtest.h"

#define DEBUG_TYPE "format-test"

namespace clang {
namespace format {

class FormatTestProto : public ::testing::Test {
protected:
  static std::string format(llvm::StringRef Code, unsigned Offset,
                            unsigned Length, const FormatStyle &Style) {
    DEBUG(llvm::errs() << "---\n");
    DEBUG(llvm::errs() << Code << "\n\n");
    std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
    tooling::Replacements Replaces = reformat(Style, Code, Ranges);
    auto Result = applyAllReplacements(Code, Replaces);
    EXPECT_TRUE(static_cast<bool>(Result));
    DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
    return *Result;
  }

  static std::string format(llvm::StringRef Code) {
    FormatStyle Style = getGoogleStyle(FormatStyle::LK_Proto);
    Style.ColumnLimit = 60; // To make writing tests easier.
    return format(Code, 0, Code.size(), Style);
  }

  static void verifyFormat(llvm::StringRef Code) {
    EXPECT_EQ(Code.str(), format(test::messUp(Code)));
  }
};

TEST_F(FormatTestProto, FormatsMessages) {
  verifyFormat("message SomeMessage {\n"
               "  required int32 field1 = 1;\n"
               "}");
  verifyFormat("message SomeMessage {\n"
               "  required .absolute.Reference field1 = 1;\n"
               "}");
  verifyFormat("message SomeMessage {\n"
               "  required int32 field1 = 1;\n"
               "  optional string field2 = 2 [default = \"2\"]\n"
               "}");

  verifyFormat("message SomeMessage {\n"
               "  optional really.really.long.qualified.type.aaa.aaaaaaa\n"
               "      fiiiiiiiiiiiiiiiiiiiiiiiiield = 1;\n"
               "  optional\n"
               "      really.really.long.qualified.type.aaa.aaaaaaa.aaaaaaaa\n"
               "          another_fiiiiiiiiiiiiiiiiiiiiield = 2;\n"
               "}");
  verifyFormat("message SomeMessage {\n"
               "  map<string, Project> projects = 1;\n"
               "  optional map<string, int32> size_projects = 2;\n"
               "  map<int, really.really.really.long.qualified.type.nameeee>\n"
               "      projects = 3;\n"
               "  map<int, really.really.really.really.long.qualified.type\n"
               "               .nameeee> projects = 4;\n"
               "  map<int,\n"
               "      reallyreallyreallyreallyreallyreallyreallylongname>\n"
               "      projects = 5;\n"
               "  map<int, Project>\n"
               "      longlonglonglonglonglonglonglonglonglongonglon = 6;\n"
               "  map<releleallyreallyreallyreallyreallyreallyreallylongname,\n"
               "      int> projects = 7;\n"
               "  map<releleallyreallyreallyreallyreallyreallyreallylongname,\n"
               "      releleallyreallyreallyreallyreallyreallyreallylongname>\n"
               "      releleallyreallyreallyreallyreallyreallyreallylongnam =\n"
               "          8;\n"
               "  map<relele.llyreal.yreallyr.allyreally.eallyreal\n"
               "          .sauenirylongname,\n"
               "      really.really.really.really.long.qualified.type\n"
               "          .nameeee> projects = 9;\n"
               "}");
}

TEST_F(FormatTestProto, KeywordsInOtherLanguages) {
  verifyFormat("optional string operator = 1;");
}

TEST_F(FormatTestProto, FormatsEnums) {
  verifyFormat("enum Type {\n"
               "  UNKNOWN = 0;\n"
               "  TYPE_A = 1;\n"
               "  TYPE_B = 2;\n"
               "};");
  verifyFormat("enum Type {\n"
               "  UNKNOWN = 0 [(some_options) = {a: aa, b: bb}];\n"
               "};");
  verifyFormat("enum Type {\n"
               "  UNKNOWN = 0 [(some_options) = {\n"
               "    a: aa,  // wrap\n"
               "    b: bb\n"
               "  }];\n"
               "};");
}

TEST_F(FormatTestProto, UnderstandsReturns) {
  verifyFormat("rpc Search(SearchRequest) returns (SearchResponse);");
}

TEST_F(FormatTestProto, MessageFieldAttributes) {
  verifyFormat("optional string test = 1 [default = \"test\"];");
  verifyFormat("optional bool a = 1 [default = true, deprecated = true];");
  verifyFormat("optional LongMessageType long_proto_field = 1 [\n"
               "  default = REALLY_REALLY_LONG_CONSTANT_VALUE,\n"
               "  deprecated = true\n"
               "];");
  verifyFormat("optional LongMessageType long_proto_field = 1\n"
               "    [default = REALLY_REALLY_LONG_CONSTANT_VALUE];");
  verifyFormat("repeated double value = 1\n"
               "    [(aaaaaaa.aaaaaaaaa) = {aaaaaaaaaaaaaaaaa: AAAAAAAA}];");
  verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
               "  aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n"
               "  bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
               "}];");
  verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
               "  aaaaaaaaaaaaaaaa: AAAAAAAAAA\n"
               "  bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
               "}];");
  verifyFormat("repeated double value = 1 [\n"
               "  (aaaaaaa.aaaaaaaaa) = {\n"
               "    aaaaaaaaaaaaaaaa: AAAAAAAAAA\n"
               "    bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
               "  },\n"
               "  (bbbbbbb.bbbbbbbbb) = {\n"
               "    aaaaaaaaaaaaaaaa: AAAAAAAAAA\n"
               "    bbbbbbbbbbbbbbbb: BBBBBBBBBB\n"
               "  }\n"
               "];");
  verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
               "  type: \"AAAAAAAAAA\"\n"
               "  is: \"AAAAAAAAAA\"\n"
               "  or: \"BBBBBBBBBB\"\n"
               "}];");
  verifyFormat("repeated double value = 1 [(aaaaaaa.aaaaaaaaa) = {\n"
               "  aaaaaaaaaaaaaaaa: AAAAAAAAAA,\n"
               "  bbbbbbb: BBBB,\n"
               "  bbbb: BBB\n"
               "}];");
  verifyFormat("optional AAA aaa = 1 [\n"
               "  foo = {\n"
               "    key: 'a'  //\n"
               "  },\n"
               "  bar = {\n"
               "    key: 'a'  //\n"
               "  }\n"
               "];");
  verifyFormat("optional string test = 1 [default =\n"
               "                              \"test\"\n"
               "                              \"test\"];");
  verifyFormat("optional Aaaaaaaa aaaaaaaa = 12 [\n"
               "  (aaa) = aaaa,\n"
               "  (bbbbbbbbbbbbbbbbbbbbbbbbbb) = {\n"
               "    aaaaaaaaaaaaaaaaa: true,\n"
               "    aaaaaaaaaaaaaaaa: true\n"
               "  }\n"
               "];");
}

TEST_F(FormatTestProto, DoesntWrapFileOptions) {
  EXPECT_EQ(
      "option java_package = "
      "\"some.really.long.package.that.exceeds.the.column.limit\";",
      format("option    java_package   =    "
             "\"some.really.long.package.that.exceeds.the.column.limit\";"));
}

TEST_F(FormatTestProto, FormatsOptions) {
  verifyFormat("option (MyProto.options) = {\n"
               "  field_a: OK\n"
               "  field_b: \"OK\"\n"
               "  field_c: \"OK\"\n"
               "  msg_field: {field_d: 123}\n"
               "};");
  verifyFormat("option (MyProto.options) = {\n"
               "  field_a: OK\n"
               "  field_b: \"OK\"\n"
               "  field_c: \"OK\"\n"
               "  msg_field: {field_d: 123 field_e: OK}\n"
               "};");
  verifyFormat("option (MyProto.options) = {\n"
               "  field_a: OK  // Comment\n"
               "  field_b: \"OK\"\n"
               "  field_c: \"OK\"\n"
               "  msg_field: {field_d: 123}\n"
               "};");
  verifyFormat("option (MyProto.options) = {\n"
               "  field_c: \"OK\"\n"
               "  msg_field{field_d: 123}\n"
               "};");

  // Support syntax with <> instead of {}.
  verifyFormat("option (MyProto.options) = {\n"
               "  field_c: \"OK\",\n"
               "  msg_field: <field_d: 123>\n"
               "};");
}

TEST_F(FormatTestProto, FormatsService) {
  verifyFormat("service SearchService {\n"
               "  rpc Search(SearchRequest) returns (SearchResponse) {\n"
               "    option foo = true;\n"
               "  }\n"
               "};");
}

TEST_F(FormatTestProto, ExtendingMessage) {
  verifyFormat("extend .foo.Bar {\n"
               "}");
}

TEST_F(FormatTestProto, FormatsImports) {
  verifyFormat("import \"a.proto\";\n"
               "import \"b.proto\";\n"
               "// comment\n"
               "message A {\n"
               "}");

  verifyFormat("import public \"a.proto\";\n"
               "import \"b.proto\";\n"
               "// comment\n"
               "message A {\n"
               "}");

  // Missing semicolons should not confuse clang-format.
  verifyFormat("import \"a.proto\"\n"
               "import \"b.proto\"\n"
               "// comment\n"
               "message A {\n"
               "}");
}

} // end namespace tooling
} // end namespace clang
<|endoftext|>


<commit_before>#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

#define ll long long
#define mem(Arr,x) memset(Arr,x,sizeof(Arr))

const int maxN=101000*10;
const int maxM=202000*10;
const int inf=2147483647;

int n,m;
int edgecnt=0,Head[maxN],Next[maxM],V[maxM];

void Add_Edge(int u,int v);
void tarjan(int u,int fa);

int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		int u,v;scanf("%d%d",&u,&v);
		Add_Edge(u,v);
	}

	tarjan(1,0);
}

void Add_Edge(int u,int v){
	Next[++edgecnt]=Head[u];Head[u]=edgecnt;V[edgecnt]=v;
	Next[+=edgecnt]=Head[v];Head[v]=edgecnt;V[edgecnt]=u;
	return;
}

void tarjan(int u,int fa)
{
	dfn[u]=low[u]=++dfncnt;
	for (int i=Head[u];i!=-1;i=Next[i])
		if (V[i]!=fa)
		{
			int v=V[i];
			if (dfn[v]==0){
				tarjan(v,u);
				low[u]=min(low[u],low[v]);
			}
			else low[u]=min(low[u],dfn[v]);
		}
}
<commit_msg>2018.7.15 am<commit_after>#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

#define ll long long
#define mem(Arr,x) memset(Arr,x,sizeof(Arr))

const int maxN=101000*2;
const int maxM=202000*20;
const int maxBit=20;
const int inf=2147483647;

int n,m,Q,nodecnt;
int edgecnt=0,Head[maxN],Next[maxM],V[maxM];
int dfncnt,dfn[maxN],low[maxN],St[maxN],top=0;
vector<int> T[maxN];
int Fa[maxBit][maxN],Depth[maxN],W[maxN];

void Add_Edge(int u,int v);
void tarjan(int u,int fa);
void dfs_fa(int u,int fa);
int LCA(int u,int v);
void dfs_calc(int u,int fa);

int main()
{
	mem(Head,-1);
	scanf("%d%d%d",&n,&m,&Q);
	for (int i=1;i<=m;i++)
	{
		int u,v;scanf("%d%d",&u,&v);
		Add_Edge(u,v);
	}

	nodecnt=n;
	tarjan(1,0);

	/*
	for (int i=1;i<=nodecnt;i++)
		for (int j=0;j<T[i].size();j++)
			cout<<i<<"->"<<T[i][j]<<endl;
	//*/

	Depth[1]=1;
	dfs_fa(1,0);

	for (int i=1;i<maxBit;i++)
		for (int j=1;j<=nodecnt;j++)
			Fa[i][j]=Fa[i-1][Fa[i-1][j]];

	while (Q--)
	{
		int p,q;scanf("%d%d",&p,&q);
		int lca=LCA(p,q);
		W[p]++;W[q]++;W[lca]--;W[Fa[0][lca]]--;
	}

	dfs_calc(1,0);

	for (int i=1;i<=n;i++) printf("%d\n",W[i]);

	return 0;
}

void Add_Edge(int u,int v){
	Next[++edgecnt]=Head[u];Head[u]=edgecnt;V[edgecnt]=v;
	Next[++edgecnt]=Head[v];Head[v]=edgecnt;V[edgecnt]=u;
	return;
}

void tarjan(int u,int fa)
{
	dfn[u]=low[u]=++dfncnt;St[++top]=u;
	for (int i=Head[u];i!=-1;i=Next[i])
		//if (V[i]!=fa)
		{
			int v=V[i];
			if (dfn[v]==0){
				tarjan(v,u);
				low[u]=min(low[u],low[v]);
				if (low[v]>=dfn[u])
				{
					nodecnt++;int w;
					do w=St[top--],T[w].push_back(nodecnt),T[nodecnt].push_back(w);
					while (w!=u);
					St[++top]=u;
				}
				//else T[u].push_back(v),T[v].push_back(u);
			}
			else low[u]=min(low[u],dfn[v]);
		}
	return;
}

void dfs_fa(int u,int fa)
{
	int sz=T[u].size();
	for (int i=0;i<sz;i++)
		if (T[u][i]!=fa){
			Depth[T[u][i]]=Depth[u]+1;Fa[0][T[u][i]]=u;
			dfs_fa(T[u][i],u);
		}
	return;
}

int LCA(int u,int v)
{
	if (Depth[u]<Depth[v]) swap(u,v);
	for (int i=maxBit-1;i>=0;i--) if ((Fa[i][u])&&(Depth[Fa[i][u]]>=Depth[v])) u=Fa[i][u];
	if (u==v) return u;
	for (int i=maxBit-1;i>=0;i--) if ((Fa[i][u])&&(Fa[i][v])&&(Fa[i][u]!=Fa[i][v])) u=Fa[i][u],v=Fa[i][v];
	return Fa[0][u];
}

void dfs_calc(int u,int fa)
{
	int sz=T[u].size();
	for (int i=0;i<sz;i++)
		if (T[u][i]!=fa){
			dfs_calc(T[u][i],u);W[u]+=W[T[u][i]];
		}
	return;
}
/*
4 4 2
1 2
1 3
2 3
1 4
4 2
4 3
//*/
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ModuleCache.h"
#include "TestingSupport/TestUtilities.h"

using namespace lldb_private;
using namespace lldb;

namespace {

class ModuleCacheTest : public testing::Test {
public:
  static void SetUpTestCase();

  static void TearDownTestCase();

protected:
  static FileSpec s_cache_dir;
  static std::string s_test_executable;

  void TryGetAndPut(const FileSpec &cache_dir, const char *hostname,
                    bool expect_download);
};
}

FileSpec ModuleCacheTest::s_cache_dir;
std::string ModuleCacheTest::s_test_executable;

static const char dummy_hostname[] = "dummy_hostname";
static const char dummy_remote_dir[] = "bin";
static const char module_name[] = "TestModule.so";
static const char module_uuid[] =
    "F4E7E991-9B61-6AD4-0073-561AC3D9FA10-C043A476";
static const uint32_t uuid_bytes = 20;
static const size_t module_size = 5602;

static FileSpec GetDummyRemotePath() {
  FileSpec fs("/", false, FileSpec::ePathSyntaxPosix);
  fs.AppendPathComponent(dummy_remote_dir);
  fs.AppendPathComponent(module_name);
  return fs;
}

static FileSpec GetUuidView(FileSpec spec) {
  spec.AppendPathComponent(".cache");
  spec.AppendPathComponent(module_uuid);
  spec.AppendPathComponent(module_name);
  return spec;
}

static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
  spec.AppendPathComponent(hostname);
  spec.AppendPathComponent(dummy_remote_dir);
  spec.AppendPathComponent(module_name);
  return spec;
}

void ModuleCacheTest::SetUpTestCase() {
  HostInfo::Initialize();
  ObjectFileELF::Initialize();

  FileSpec tmpdir_spec;
  HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, s_cache_dir);
  s_test_executable = GetInputFilePath(module_name);
}

void ModuleCacheTest::TearDownTestCase() {
  ObjectFileELF::Terminate();
  HostInfo::Terminate();
}

static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
  FileSpec uuid_view = GetUuidView(cache_dir);
  EXPECT_TRUE(uuid_view.Exists()) << "uuid_view is: " << uuid_view.GetCString();
  EXPECT_EQ(module_size, uuid_view.GetByteSize());

  FileSpec sysroot_view = GetSysrootView(cache_dir, hostname);
  EXPECT_TRUE(sysroot_view.Exists()) << "sysroot_view is: "
                                     << sysroot_view.GetCString();
  EXPECT_EQ(module_size, sysroot_view.GetByteSize());
}

void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir,
                                   const char *hostname, bool expect_download) {
  ModuleCache mc;
  ModuleSpec module_spec;
  module_spec.GetFileSpec() = GetDummyRemotePath();
  module_spec.GetUUID().SetFromCString(module_uuid, uuid_bytes);
  module_spec.SetObjectSize(module_size);
  ModuleSP module_sp;
  bool did_create;
  bool download_called = false;

  Status error = mc.GetAndPut(
      cache_dir, hostname, module_spec,
      [this, &download_called](const ModuleSpec &module_spec,
                               const FileSpec &tmp_download_file_spec) {
        download_called = true;
        EXPECT_STREQ(GetDummyRemotePath().GetCString(),
                     module_spec.GetFileSpec().GetCString());
        std::error_code ec = llvm::sys::fs::copy_file(
            s_test_executable, tmp_download_file_spec.GetCString());
        EXPECT_FALSE(ec);
        return Status();
      },
      [](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) {
        return Status("Not supported.");
      },
      module_sp, &did_create);
  EXPECT_EQ(expect_download, download_called);

  EXPECT_TRUE(error.Success()) << "Error was: " << error.AsCString();
  EXPECT_TRUE(did_create);
  ASSERT_TRUE(bool(module_sp));

  SymbolContextList sc_list;
  EXPECT_EQ(1u, module_sp->FindFunctionSymbols(ConstString("boom"),
                                               eFunctionNameTypeFull, sc_list));
  EXPECT_STREQ(GetDummyRemotePath().GetCString(),
               module_sp->GetPlatformFileSpec().GetCString());
  EXPECT_STREQ(module_uuid, module_sp->GetUUID().GetAsString().c_str());
}

TEST_F(ModuleCacheTest, GetAndPut) {
  FileSpec test_cache_dir = s_cache_dir;
  test_cache_dir.AppendPathComponent("GetAndPut");

  const bool expect_download = true;
  TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
  VerifyDiskState(test_cache_dir, dummy_hostname);
}

TEST_F(ModuleCacheTest, GetAndPutUuidExists) {
  FileSpec test_cache_dir = s_cache_dir;
  test_cache_dir.AppendPathComponent("GetAndPutUuidExists");

  FileSpec uuid_view = GetUuidView(test_cache_dir);
  std::error_code ec =
      llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());
  ASSERT_FALSE(ec);
  ec = llvm::sys::fs::copy_file(s_test_executable, uuid_view.GetCString());
  ASSERT_FALSE(ec);

  const bool expect_download = false;
  TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
  VerifyDiskState(test_cache_dir, dummy_hostname);
}

TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) {
  FileSpec test_cache_dir = s_cache_dir;
  test_cache_dir.AppendPathComponent("GetAndPutStrangeHostname");

  const bool expect_download = true;
  TryGetAndPut(test_cache_dir, "tab\tcolon:asterisk*", expect_download);
  VerifyDiskState(test_cache_dir, "tab_colon_asterisk_");
}
<commit_msg>Fix a compiler warning in ModuleCacheTest.cpp, NFC<commit_after>#include "gtest/gtest.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ModuleCache.h"
#include "TestingSupport/TestUtilities.h"

using namespace lldb_private;
using namespace lldb;

namespace {

class ModuleCacheTest : public testing::Test {
public:
  static void SetUpTestCase();

  static void TearDownTestCase();

protected:
  static FileSpec s_cache_dir;
  static std::string s_test_executable;

  void TryGetAndPut(const FileSpec &cache_dir, const char *hostname,
                    bool expect_download);
};
}

FileSpec ModuleCacheTest::s_cache_dir;
std::string ModuleCacheTest::s_test_executable;

static const char dummy_hostname[] = "dummy_hostname";
static const char dummy_remote_dir[] = "bin";
static const char module_name[] = "TestModule.so";
static const char module_uuid[] =
    "F4E7E991-9B61-6AD4-0073-561AC3D9FA10-C043A476";
static const uint32_t uuid_bytes = 20;
static const size_t module_size = 5602;

static FileSpec GetDummyRemotePath() {
  FileSpec fs("/", false, FileSpec::ePathSyntaxPosix);
  fs.AppendPathComponent(dummy_remote_dir);
  fs.AppendPathComponent(module_name);
  return fs;
}

static FileSpec GetUuidView(FileSpec spec) {
  spec.AppendPathComponent(".cache");
  spec.AppendPathComponent(module_uuid);
  spec.AppendPathComponent(module_name);
  return spec;
}

static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
  spec.AppendPathComponent(hostname);
  spec.AppendPathComponent(dummy_remote_dir);
  spec.AppendPathComponent(module_name);
  return spec;
}

void ModuleCacheTest::SetUpTestCase() {
  HostInfo::Initialize();
  ObjectFileELF::Initialize();

  FileSpec tmpdir_spec;
  HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, s_cache_dir);
  s_test_executable = GetInputFilePath(module_name);
}

void ModuleCacheTest::TearDownTestCase() {
  ObjectFileELF::Terminate();
  HostInfo::Terminate();
}

static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
  FileSpec uuid_view = GetUuidView(cache_dir);
  EXPECT_TRUE(uuid_view.Exists()) << "uuid_view is: " << uuid_view.GetCString();
  EXPECT_EQ(module_size, uuid_view.GetByteSize());

  FileSpec sysroot_view = GetSysrootView(cache_dir, hostname);
  EXPECT_TRUE(sysroot_view.Exists()) << "sysroot_view is: "
                                     << sysroot_view.GetCString();
  EXPECT_EQ(module_size, sysroot_view.GetByteSize());
}

void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir,
                                   const char *hostname, bool expect_download) {
  ModuleCache mc;
  ModuleSpec module_spec;
  module_spec.GetFileSpec() = GetDummyRemotePath();
  module_spec.GetUUID().SetFromCString(module_uuid, uuid_bytes);
  module_spec.SetObjectSize(module_size);
  ModuleSP module_sp;
  bool did_create;
  bool download_called = false;

  Status error = mc.GetAndPut(
      cache_dir, hostname, module_spec,
      [&download_called](const ModuleSpec &module_spec,
                         const FileSpec &tmp_download_file_spec) {
        download_called = true;
        EXPECT_STREQ(GetDummyRemotePath().GetCString(),
                     module_spec.GetFileSpec().GetCString());
        std::error_code ec = llvm::sys::fs::copy_file(
            s_test_executable, tmp_download_file_spec.GetCString());
        EXPECT_FALSE(ec);
        return Status();
      },
      [](const ModuleSP &module_sp, const FileSpec &tmp_download_file_spec) {
        return Status("Not supported.");
      },
      module_sp, &did_create);
  EXPECT_EQ(expect_download, download_called);

  EXPECT_TRUE(error.Success()) << "Error was: " << error.AsCString();
  EXPECT_TRUE(did_create);
  ASSERT_TRUE(bool(module_sp));

  SymbolContextList sc_list;
  EXPECT_EQ(1u, module_sp->FindFunctionSymbols(ConstString("boom"),
                                               eFunctionNameTypeFull, sc_list));
  EXPECT_STREQ(GetDummyRemotePath().GetCString(),
               module_sp->GetPlatformFileSpec().GetCString());
  EXPECT_STREQ(module_uuid, module_sp->GetUUID().GetAsString().c_str());
}

TEST_F(ModuleCacheTest, GetAndPut) {
  FileSpec test_cache_dir = s_cache_dir;
  test_cache_dir.AppendPathComponent("GetAndPut");

  const bool expect_download = true;
  TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
  VerifyDiskState(test_cache_dir, dummy_hostname);
}

TEST_F(ModuleCacheTest, GetAndPutUuidExists) {
  FileSpec test_cache_dir = s_cache_dir;
  test_cache_dir.AppendPathComponent("GetAndPutUuidExists");

  FileSpec uuid_view = GetUuidView(test_cache_dir);
  std::error_code ec =
      llvm::sys::fs::create_directories(uuid_view.GetDirectory().GetCString());
  ASSERT_FALSE(ec);
  ec = llvm::sys::fs::copy_file(s_test_executable, uuid_view.GetCString());
  ASSERT_FALSE(ec);

  const bool expect_download = false;
  TryGetAndPut(test_cache_dir, dummy_hostname, expect_download);
  VerifyDiskState(test_cache_dir, dummy_hostname);
}

TEST_F(ModuleCacheTest, GetAndPutStrangeHostname) {
  FileSpec test_cache_dir = s_cache_dir;
  test_cache_dir.AppendPathComponent("GetAndPutStrangeHostname");

  const bool expect_download = true;
  TryGetAndPut(test_cache_dir, "tab\tcolon:asterisk*", expect_download);
  VerifyDiskState(test_cache_dir, "tab_colon_asterisk_");
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifdef USE_RANDR

#include <prex.h>
#include <X11/extensions/Xrandr.h>
#include <postx.h>

#include "osl/module.h"
#include "rtl/ustring.hxx"

namespace
{

# ifdef XRANDR_DLOPEN

class RandRWrapper
{
    oslModule m_pRandRLib;

    // function pointers
    Bool(*m_pXRRQueryExtension)(Display*,int*,int*);
    Status(*m_pXRRQueryVersion)(Display*,int*,int*);
    XRRScreenConfiguration*(*m_pXRRGetScreenInfo)(Display*,Drawable);
    void(*m_pXRRFreeScreenConfigInfo)(XRRScreenConfiguration*);
    void(*m_pXRRSelectInput)(Display*,XLIB_Window,int);
    int(*m_pXRRUpdateConfiguration)(XEvent*);
    XRRScreenSize*(*m_pXRRSizes)(Display*,int,int*);
    XRRScreenSize*(*m_pXRRConfigSizes)(XRRScreenConfiguration*,int*);
    SizeID(*m_pXRRConfigCurrentConfiguration)(XRRScreenConfiguration*,Rotation*);
    int(*m_pXRRRootToScreen)(Display*, XLIB_Window);

    bool m_bValid;

    void initFromModule();

    RandRWrapper(Display*);
    ~RandRWrapper();
public:
    static RandRWrapper& get(Display*);
    static void releaseWrapper();

    Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
    {
        Bool bRet = False;
        if( m_bValid )
            bRet = m_pXRRQueryExtension( i_pDisp, o_event_base, o_error_base );
        return bRet;
    }
    Status XRRQueryVersion( Display* i_pDisp, int* o_major, int* o_minor )
    {
        return m_bValid ? m_pXRRQueryVersion( i_pDisp, o_major, o_minor ) : 0;
    }
    XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
    {
        return m_bValid ? m_pXRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
    }
    void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
    {
        if( m_bValid )
            m_pXRRFreeScreenConfigInfo( i_pConfig );
    }
    void XRRSelectInput( Display* i_pDisp, XLIB_Window i_window, int i_nMask )
    {
        if( m_bValid )
            m_pXRRSelectInput( i_pDisp, i_window, i_nMask );
    }
    int XRRUpdateConfiguration( XEvent* i_pEvent )
    {
        return m_bValid ? m_pXRRUpdateConfiguration( i_pEvent ) : 0;
    }
    XRRScreenSize* XRRSizes( Display* i_pDisp, int i_screen, int* o_nscreens )
    {
        return m_bValid ? m_pXRRSizes( i_pDisp, i_screen, o_nscreens ) : NULL;
    }
    XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
    {
        return m_bValid ? m_pXRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
    }
    SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
    {
        return m_bValid ? m_pXRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
    }
    int XRRRootToScreen( Display *dpy, XLIB_Window root )
    {
        return m_bValid ? m_pXRRRootToScreen( dpy, root ) : -1;
    }
};

void RandRWrapper::initFromModule()
{
    m_pXRRQueryExtension = (Bool(*)(Display*,int*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRQueryExtension" );
    m_pXRRQueryVersion = (Status(*)(Display*,int*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRQueryVersion" );
    m_pXRRGetScreenInfo = (XRRScreenConfiguration*(*)(Display*,Drawable))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRGetScreenInfo" );
    m_pXRRFreeScreenConfigInfo = (void(*)(XRRScreenConfiguration*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRFreeScreenConfigInfo" );
    m_pXRRSelectInput = (void(*)(Display*,XLIB_Window,int))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRSelectInput" );
    m_pXRRUpdateConfiguration = (int(*)(XEvent*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRUpdateConfiguration" );
    m_pXRRSizes = (XRRScreenSize*(*)(Display*,int,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRSizes" );
    m_pXRRConfigSizes = (XRRScreenSize*(*)(XRRScreenConfiguration*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigSizes" );
    m_pXRRConfigCurrentConfiguration = (SizeID(*)(XRRScreenConfiguration*,Rotation*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigCurrentConfiguration" );
    m_pXRRRootToScreen = (int(*)(Display*,XLIB_Window))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRRootToScreen" );

    m_bValid = m_pXRRQueryExtension             &&
               m_pXRRQueryVersion               &&
               m_pXRRGetScreenInfo              &&
               m_pXRRFreeScreenConfigInfo       &&
               m_pXRRSelectInput                &&
               m_pXRRUpdateConfiguration        &&
               m_pXRRSizes                      &&
               m_pXRRConfigSizes                &&
               m_pXRRConfigCurrentConfiguration &&
               m_pXRRRootToScreen
               ;
}

RandRWrapper::RandRWrapper( Display* pDisplay ) :
        m_pRandRLib( NULL ),
        m_pXRRQueryExtension( NULL ),
        m_pXRRQueryVersion( NULL ),
        m_pXRRGetScreenInfo( NULL ),
        m_pXRRFreeScreenConfigInfo( NULL ),
        m_pXRRSelectInput( NULL ),
        m_pXRRUpdateConfiguration( NULL ),
        m_pXRRSizes( NULL ),
        m_pXRRConfigSizes( NULL ),
        m_pXRRConfigCurrentConfiguration( NULL ),
        m_pXRRRootToScreen( NULL ),
        m_bValid( false )
{
    // first try in process space (e.g. gtk links that ?)
    initFromModule();
    if( ! m_bValid )
    {
        // load and resolve dependencies immediately
        // rationale: there are older distributions where libXrandr.so.2 is not linked
        // with libXext.so, resulting in a missing symbol and terminating the office
        // obviously they expected libXext to be linked in global symbolspace (that is
        // linked by the application), which is not the case with us (because we want
        // to be able to run in headless mode even without an installed X11 library)
        m_pRandRLib = osl_loadModule( "libXrandr.so.2", SAL_LOADMODULE_DEFAULT | SAL_LOADMODULE_NOW );
        initFromModule();
    }
    if( m_bValid )
    {
        int nEventBase = 0, nErrorBase = 0;
        if( ! m_pXRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
            m_bValid = false;
    }
}

RandRWrapper::~RandRWrapper()
{
    if( m_pRandRLib )
        osl_unloadModule( m_pRandRLib );
}

static RandRWrapper* pWrapper = NULL;

RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
{
    if( ! pWrapper )
        pWrapper = new RandRWrapper( i_pDisplay );
    return *pWrapper;
}

void RandRWrapper::releaseWrapper()
{
    delete pWrapper;
    pWrapper = NULL;
}

# else

class RandRWrapper
{
    bool m_bValid;

    RandRWrapper(Display*);
public:
    static RandRWrapper& get(Display*);
    static void releaseWrapper();

    Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
    {
        Bool bRet = False;
        if( m_bValid )
            bRet = ::XRRQueryExtension( i_pDisp, o_event_base, o_error_base );
        return bRet;
    }
    Status XRRQueryVersion( Display* i_pDisp, int* o_major, int* o_minor )
    {
        return m_bValid ? ::XRRQueryVersion( i_pDisp, o_major, o_minor ) : 0;
    }
    XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
    {
        return m_bValid ? ::XRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
    }
    void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
    {
        if( m_bValid )
            ::XRRFreeScreenConfigInfo( i_pConfig );
    }
    void XRRSelectInput( Display* i_pDisp, XLIB_Window i_window, int i_nMask )
    {
        if( m_bValid )
            ::XRRSelectInput( i_pDisp, i_window, i_nMask );
    }
    int XRRUpdateConfiguration( XEvent* i_pEvent )
    {
        return m_bValid ? ::XRRUpdateConfiguration( i_pEvent ) : 0;
    }
    XRRScreenSize* XRRSizes( Display* i_pDisp, int i_screen, int* o_nscreens )
    {
        return m_bValid ? ::XRRSizes( i_pDisp, i_screen, o_nscreens ) : NULL;
    }
    XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
    {
        return m_bValid ? ::XRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
    }
    SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
    {
        return m_bValid ? ::XRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
    }
    int XRRRootToScreen( Display *dpy, XLIB_Window root )
    {
        return m_bValid ? ::XRRRootToScreen( dpy, root ) : -1;
    }
};

RandRWrapper::RandRWrapper( Display* pDisplay ) :
    m_bValid( true )
{
    int nEventBase = 0, nErrorBase = 0;
    if( !XRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
        m_bValid = false;
}

static RandRWrapper* pWrapper = NULL;

RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
{
    if( ! pWrapper )
        pWrapper = new RandRWrapper( i_pDisplay );
    return *pWrapper;
}

void RandRWrapper::releaseWrapper()
{
    delete pWrapper;
    pWrapper = NULL;
}

#endif

} // namespace

#endif

#include "unx/saldisp.hxx"
#include "unx/salframe.h"
#if OSL_DEBUG_LEVEL > 1
#include <cstdio>
#endif

void SalDisplay::InitRandR( XLIB_Window aRoot ) const
{
    #ifdef USE_RANDR
    if( m_bUseRandRWrapper )
        RandRWrapper::get( GetDisplay() ).XRRSelectInput( GetDisplay(), aRoot, RRScreenChangeNotifyMask );
    #else
    (void)aRoot;
    #endif
}

void SalDisplay::DeInitRandR()
{
    #ifdef USE_RANDR
    if( m_bUseRandRWrapper )
        RandRWrapper::releaseWrapper();
#if OSL_DEBUG_LEVEL > 1
    fprintf( stderr, "SalDisplay::DeInitRandR()\n" );
#endif
    #endif
}

int SalDisplay::processRandREvent( XEvent* pEvent )
{
    int nRet = 0;
    #ifdef USE_RANDR
    XConfigureEvent* pCnfEvent=(XConfigureEvent*)pEvent;
    if( m_bUseRandRWrapper && pWrapper && pWrapper->XRRRootToScreen(GetDisplay(),pCnfEvent->window) != -1 )
    {
        nRet = pWrapper->XRRUpdateConfiguration( pEvent );
        if( nRet == 1 && pEvent->type != ConfigureNotify) // this should then be a XRRScreenChangeNotifyEvent
        {
            // update screens
            bool bNotify = false;
            for( size_t i = 0; i < m_aScreens.size(); i++ )
            {
                if( m_aScreens[i].m_bInit )
                {
                    XRRScreenConfiguration *pConfig = NULL;
                    XRRScreenSize *pSizes = NULL;
                    int nSizes = 0;
                    Rotation nRot = 0;
                    SizeID nId = 0;

                    pConfig = pWrapper->XRRGetScreenInfo( GetDisplay(), m_aScreens[i].m_aRoot );
                    nId = pWrapper->XRRConfigCurrentConfiguration( pConfig, &nRot );
                    pSizes = pWrapper->XRRConfigSizes( pConfig, &nSizes );
                    XRRScreenSize *pTargetSize = pSizes + nId;

                    bNotify = bNotify ||
                              m_aScreens[i].m_aSize.Width() != pTargetSize->width ||
                              m_aScreens[i].m_aSize.Height() != pTargetSize->height;

                    m_aScreens[i].m_aSize = Size( pTargetSize->width, pTargetSize->height );

                    pWrapper->XRRFreeScreenConfigInfo( pConfig );

                    #if OSL_DEBUG_LEVEL > 1
                    fprintf( stderr, "screen %d changed to size %dx%d\n", (int)i, (int)pTargetSize->width, (int)pTargetSize->height );
                    #endif
                }
            }
            if( bNotify )
                emitDisplayChanged();
        }
    }
    #else
    (void)pEvent;
    #endif
    return nRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>-Werror,-Wunused-member-function<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifdef USE_RANDR

#include <prex.h>
#include <X11/extensions/Xrandr.h>
#include <postx.h>

#include "osl/module.h"
#include "rtl/ustring.hxx"

namespace
{

# ifdef XRANDR_DLOPEN

class RandRWrapper
{
    oslModule m_pRandRLib;

    // function pointers
    Bool(*m_pXRRQueryExtension)(Display*,int*,int*);
    XRRScreenConfiguration*(*m_pXRRGetScreenInfo)(Display*,Drawable);
    void(*m_pXRRFreeScreenConfigInfo)(XRRScreenConfiguration*);
    void(*m_pXRRSelectInput)(Display*,XLIB_Window,int);
    int(*m_pXRRUpdateConfiguration)(XEvent*);
    XRRScreenSize*(*m_pXRRConfigSizes)(XRRScreenConfiguration*,int*);
    SizeID(*m_pXRRConfigCurrentConfiguration)(XRRScreenConfiguration*,Rotation*);
    int(*m_pXRRRootToScreen)(Display*, XLIB_Window);

    bool m_bValid;

    void initFromModule();

    RandRWrapper(Display*);
    ~RandRWrapper();
public:
    static RandRWrapper& get(Display*);
    static void releaseWrapper();

    Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
    {
        Bool bRet = False;
        if( m_bValid )
            bRet = m_pXRRQueryExtension( i_pDisp, o_event_base, o_error_base );
        return bRet;
    }
    XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
    {
        return m_bValid ? m_pXRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
    }
    void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
    {
        if( m_bValid )
            m_pXRRFreeScreenConfigInfo( i_pConfig );
    }
    void XRRSelectInput( Display* i_pDisp, XLIB_Window i_window, int i_nMask )
    {
        if( m_bValid )
            m_pXRRSelectInput( i_pDisp, i_window, i_nMask );
    }
    int XRRUpdateConfiguration( XEvent* i_pEvent )
    {
        return m_bValid ? m_pXRRUpdateConfiguration( i_pEvent ) : 0;
    }
    XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
    {
        return m_bValid ? m_pXRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
    }
    SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
    {
        return m_bValid ? m_pXRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
    }
    int XRRRootToScreen( Display *dpy, XLIB_Window root )
    {
        return m_bValid ? m_pXRRRootToScreen( dpy, root ) : -1;
    }
};

void RandRWrapper::initFromModule()
{
    m_pXRRQueryExtension = (Bool(*)(Display*,int*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRQueryExtension" );
    m_pXRRGetScreenInfo = (XRRScreenConfiguration*(*)(Display*,Drawable))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRGetScreenInfo" );
    m_pXRRFreeScreenConfigInfo = (void(*)(XRRScreenConfiguration*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRFreeScreenConfigInfo" );
    m_pXRRSelectInput = (void(*)(Display*,XLIB_Window,int))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRSelectInput" );
    m_pXRRUpdateConfiguration = (int(*)(XEvent*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRUpdateConfiguration" );
    m_pXRRConfigSizes = (XRRScreenSize*(*)(XRRScreenConfiguration*,int*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigSizes" );
    m_pXRRConfigCurrentConfiguration = (SizeID(*)(XRRScreenConfiguration*,Rotation*))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRConfigCurrentConfiguration" );
    m_pXRRRootToScreen = (int(*)(Display*,XLIB_Window))osl_getAsciiFunctionSymbol( m_pRandRLib, "XRRRootToScreen" );

    m_bValid = m_pXRRQueryExtension             &&
               m_pXRRGetScreenInfo              &&
               m_pXRRFreeScreenConfigInfo       &&
               m_pXRRSelectInput                &&
               m_pXRRUpdateConfiguration        &&
               m_pXRRConfigSizes                &&
               m_pXRRConfigCurrentConfiguration &&
               m_pXRRRootToScreen
               ;
}

RandRWrapper::RandRWrapper( Display* pDisplay ) :
        m_pRandRLib( NULL ),
        m_pXRRQueryExtension( NULL ),
        m_pXRRGetScreenInfo( NULL ),
        m_pXRRFreeScreenConfigInfo( NULL ),
        m_pXRRSelectInput( NULL ),
        m_pXRRUpdateConfiguration( NULL ),
        m_pXRRConfigSizes( NULL ),
        m_pXRRConfigCurrentConfiguration( NULL ),
        m_pXRRRootToScreen( NULL ),
        m_bValid( false )
{
    // first try in process space (e.g. gtk links that ?)
    initFromModule();
    if( ! m_bValid )
    {
        // load and resolve dependencies immediately
        // rationale: there are older distributions where libXrandr.so.2 is not linked
        // with libXext.so, resulting in a missing symbol and terminating the office
        // obviously they expected libXext to be linked in global symbolspace (that is
        // linked by the application), which is not the case with us (because we want
        // to be able to run in headless mode even without an installed X11 library)
        m_pRandRLib = osl_loadModule( "libXrandr.so.2", SAL_LOADMODULE_DEFAULT | SAL_LOADMODULE_NOW );
        initFromModule();
    }
    if( m_bValid )
    {
        int nEventBase = 0, nErrorBase = 0;
        if( ! m_pXRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
            m_bValid = false;
    }
}

RandRWrapper::~RandRWrapper()
{
    if( m_pRandRLib )
        osl_unloadModule( m_pRandRLib );
}

static RandRWrapper* pWrapper = NULL;

RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
{
    if( ! pWrapper )
        pWrapper = new RandRWrapper( i_pDisplay );
    return *pWrapper;
}

void RandRWrapper::releaseWrapper()
{
    delete pWrapper;
    pWrapper = NULL;
}

# else

class RandRWrapper
{
    bool m_bValid;

    RandRWrapper(Display*);
public:
    static RandRWrapper& get(Display*);
    static void releaseWrapper();

    Bool XRRQueryExtension(Display* i_pDisp, int* o_event_base, int* o_error_base )
    {
        Bool bRet = False;
        if( m_bValid )
            bRet = ::XRRQueryExtension( i_pDisp, o_event_base, o_error_base );
        return bRet;
    }
    XRRScreenConfiguration* XRRGetScreenInfo( Display* i_pDisp, Drawable i_aDrawable )
    {
        return m_bValid ? ::XRRGetScreenInfo( i_pDisp, i_aDrawable ) : NULL;
    }
    void XRRFreeScreenConfigInfo( XRRScreenConfiguration* i_pConfig )
    {
        if( m_bValid )
            ::XRRFreeScreenConfigInfo( i_pConfig );
    }
    void XRRSelectInput( Display* i_pDisp, XLIB_Window i_window, int i_nMask )
    {
        if( m_bValid )
            ::XRRSelectInput( i_pDisp, i_window, i_nMask );
    }
    int XRRUpdateConfiguration( XEvent* i_pEvent )
    {
        return m_bValid ? ::XRRUpdateConfiguration( i_pEvent ) : 0;
    }
    XRRScreenSize* XRRConfigSizes( XRRScreenConfiguration* i_pConfig, int* o_nSizes )
    {
        return m_bValid ? ::XRRConfigSizes( i_pConfig, o_nSizes ) : NULL;
    }
    SizeID XRRConfigCurrentConfiguration( XRRScreenConfiguration* i_pConfig, Rotation* o_pRot )
    {
        return m_bValid ? ::XRRConfigCurrentConfiguration( i_pConfig, o_pRot ) : 0;
    }
    int XRRRootToScreen( Display *dpy, XLIB_Window root )
    {
        return m_bValid ? ::XRRRootToScreen( dpy, root ) : -1;
    }
};

RandRWrapper::RandRWrapper( Display* pDisplay ) :
    m_bValid( true )
{
    int nEventBase = 0, nErrorBase = 0;
    if( !XRRQueryExtension( pDisplay, &nEventBase, &nErrorBase ) )
        m_bValid = false;
}

static RandRWrapper* pWrapper = NULL;

RandRWrapper& RandRWrapper::get( Display* i_pDisplay )
{
    if( ! pWrapper )
        pWrapper = new RandRWrapper( i_pDisplay );
    return *pWrapper;
}

void RandRWrapper::releaseWrapper()
{
    delete pWrapper;
    pWrapper = NULL;
}

#endif

} // namespace

#endif

#include "unx/saldisp.hxx"
#include "unx/salframe.h"
#if OSL_DEBUG_LEVEL > 1
#include <cstdio>
#endif

void SalDisplay::InitRandR( XLIB_Window aRoot ) const
{
    #ifdef USE_RANDR
    if( m_bUseRandRWrapper )
        RandRWrapper::get( GetDisplay() ).XRRSelectInput( GetDisplay(), aRoot, RRScreenChangeNotifyMask );
    #else
    (void)aRoot;
    #endif
}

void SalDisplay::DeInitRandR()
{
    #ifdef USE_RANDR
    if( m_bUseRandRWrapper )
        RandRWrapper::releaseWrapper();
#if OSL_DEBUG_LEVEL > 1
    fprintf( stderr, "SalDisplay::DeInitRandR()\n" );
#endif
    #endif
}

int SalDisplay::processRandREvent( XEvent* pEvent )
{
    int nRet = 0;
    #ifdef USE_RANDR
    XConfigureEvent* pCnfEvent=(XConfigureEvent*)pEvent;
    if( m_bUseRandRWrapper && pWrapper && pWrapper->XRRRootToScreen(GetDisplay(),pCnfEvent->window) != -1 )
    {
        nRet = pWrapper->XRRUpdateConfiguration( pEvent );
        if( nRet == 1 && pEvent->type != ConfigureNotify) // this should then be a XRRScreenChangeNotifyEvent
        {
            // update screens
            bool bNotify = false;
            for( size_t i = 0; i < m_aScreens.size(); i++ )
            {
                if( m_aScreens[i].m_bInit )
                {
                    XRRScreenConfiguration *pConfig = NULL;
                    XRRScreenSize *pSizes = NULL;
                    int nSizes = 0;
                    Rotation nRot = 0;
                    SizeID nId = 0;

                    pConfig = pWrapper->XRRGetScreenInfo( GetDisplay(), m_aScreens[i].m_aRoot );
                    nId = pWrapper->XRRConfigCurrentConfiguration( pConfig, &nRot );
                    pSizes = pWrapper->XRRConfigSizes( pConfig, &nSizes );
                    XRRScreenSize *pTargetSize = pSizes + nId;

                    bNotify = bNotify ||
                              m_aScreens[i].m_aSize.Width() != pTargetSize->width ||
                              m_aScreens[i].m_aSize.Height() != pTargetSize->height;

                    m_aScreens[i].m_aSize = Size( pTargetSize->width, pTargetSize->height );

                    pWrapper->XRRFreeScreenConfigInfo( pConfig );

                    #if OSL_DEBUG_LEVEL > 1
                    fprintf( stderr, "screen %d changed to size %dx%d\n", (int)i, (int)pTargetSize->width, (int)pTargetSize->height );
                    #endif
                }
            }
            if( bNotify )
                emitDisplayChanged();
        }
    }
    #else
    (void)pEvent;
    #endif
    return nRet;
}

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


<commit_before>#ifndef SILICIUM_HTML_TREE_HPP
#define SILICIUM_HTML_TREE_HPP

#include <silicium/html/generator.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/trait.hpp>

namespace Si
{
	namespace html
	{
		template <std::size_t Length>
		struct exact_length : std::integral_constant<std::size_t, Length>
		{
		};

		template <std::size_t Length>
		struct min_length : std::integral_constant<std::size_t, Length>
		{
		};

		namespace detail
		{
			template <class FirstLength, class SecondLength>
			struct concatenate;

			template <std::size_t FirstLength, std::size_t SecondLength>
			struct concatenate<exact_length<FirstLength>, exact_length<SecondLength>>
			{
				typedef exact_length<FirstLength + SecondLength> type;
			};

			template <std::size_t FirstLength, std::size_t SecondLength>
			struct concatenate<min_length<FirstLength>, exact_length<SecondLength>>
			{
				typedef min_length<FirstLength + SecondLength> type;
			};

			template <std::size_t FirstLength, std::size_t SecondLength>
			struct concatenate<exact_length<FirstLength>, min_length<SecondLength>>
			{
				typedef min_length<FirstLength + SecondLength> type;
			};

			template <std::size_t FirstLength, std::size_t SecondLength>
			struct concatenate<min_length<FirstLength>, min_length<SecondLength>>
			{
				typedef min_length<FirstLength + SecondLength> type;
			};

			template <class ContentGenerator, class Length>
			struct element
			{
				typedef Length length_type;
				ContentGenerator generate;
			};

			template <class Length, class ContentGenerator>
			auto make_element(ContentGenerator &&generate)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				-> element<typename std::decay<ContentGenerator>::type, Length>
#endif
			{
				return element<typename std::decay<ContentGenerator>::type, Length>{std::forward<ContentGenerator>(generate)};
			}
		}

		typedef sink<char, success> destination_sink;

		template <class Length = min_length<0>>
		SILICIUM_TRAIT_WITH_TYPEDEFS(
			Element,
			typedef Length length_type;
			,
			((generate, (1, (destination_sink &)), void, const))
		)

		template <class Length, class ContentGenerator>
		auto dynamic(ContentGenerator &&generate)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> decltype(detail::make_element<Length>(std::forward<ContentGenerator>(generate)))
#endif
		{
			return detail::make_element<Length>(std::forward<ContentGenerator>(generate));
		}

		template <std::size_t Length>
		auto raw(char const (&content)[Length])
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> detail::element<exact_length<Length - 1>, std::function<void(sink<char, success> &)>>
#endif
		{
			return dynamic<exact_length<Length - 1>>(
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				std::function<void(sink<char, success> &)>
#endif
				([&content](sink<char, success> &destination)
			{
				Si::append(destination, content);
			}));
		}

		template <std::size_t NameLength, class Attributes, class Element, class ResultLength = typename detail::concatenate<
			typename std::decay<Element>::type::length_type,
			typename detail::concatenate<
			typename std::decay<Attributes>::type::length_type,
			exact_length<1 + (NameLength - 1) + 1 + 2 + (NameLength - 1) + 1>
			>::type
		>::type>
		auto tag(char const (&name)[NameLength], Attributes &&attributes, Element &&content)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> detail::element<ResultLength, std::function<void(sink<char, success> &)>>
#endif
		{
			return detail::make_element<ResultLength>(
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				std::function<void(sink<char, success> &)>
#endif
				([
					&name,
					SILICIUM_CAPTURE_EXPRESSION(generate_content, std::move(content.generate)),
					SILICIUM_CAPTURE_EXPRESSION(attributes, std::forward<Attributes>(attributes))
				] (sink<char, success> &destination)
				{
					html::open_attributed_element(destination, name);
					attributes.generate(destination);
					html::finish_attributes(destination);
					generate_content(destination);
					html::close_element(destination, name);
				})
			);
		}

		template <std::size_t NameLength, class Attributes, class ResultLength = typename detail::concatenate<
			min_length<1 + (NameLength - 1) + 2>,
			typename std::decay<Attributes>::type::length_type
		>::type>
		auto tag(char const (&name)[NameLength], Attributes &&attributes, empty_t)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> detail::element<ResultLength, std::function<void(sink<char, success> &)>>
#endif
		{
			return detail::make_element<ResultLength>(
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				std::function<void(sink<char, success> &)>
#endif
				([
					&name,
					SILICIUM_CAPTURE_EXPRESSION(attributes, std::forward<Attributes>(attributes))
				] (sink<char, success> &destination)
				{
					html::open_attributed_element(destination, name);
					attributes.generate(destination);
					finish_attributes_of_unpaired_tag(destination);
				})
			);
		}

		namespace detail
		{
			void no_attributes(sink<char, success> &)
			{
			}
		}

		template <std::size_t NameLength, class Element>
		auto tag(char const (&name)[NameLength], Element &&content)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> decltype(tag(name, detail::make_element<exact_length<0>>(&detail::no_attributes), std::forward<Element>(content)))
#endif
		{
			return tag(name, detail::make_element<exact_length<0>>(&detail::no_attributes), std::forward<Element>(content));
		}

		template <std::size_t KeyLength, std::size_t ValueLength>
		auto attribute(char const (&key)[KeyLength], char const (&value)[ValueLength])
		{
			static BOOST_CONSTEXPR_OR_CONST std::size_t space = 1;
			static BOOST_CONSTEXPR_OR_CONST std::size_t assign = 1;
			static BOOST_CONSTEXPR_OR_CONST std::size_t quote = 1;
			static BOOST_CONSTEXPR_OR_CONST std::size_t length = space + (KeyLength - 1) + assign + quote + (ValueLength - 1) + quote;
			return detail::make_element<min_length<length>>(
				[&key, &value](sink<char, success> &destination)
			{
				add_attribute(destination, key, value);
			});
		}

		template <std::size_t Length>
		auto text(char const (&content)[Length])
		{
			typedef min_length<Length - 1> length;
			return detail::make_element<length>([&content](sink<char, success> &destination)
			{
				html::write_string(destination, content);
			});
		}

		auto sequence()
		{
			return detail::make_element<exact_length<0>>([](sink<char, success> &)
			{
			});
		}

		template <class Head, class ...Tail>
		auto sequence(Head &&head, Tail &&...tail)
		{
			auto tail_elements = sequence(std::forward<Tail>(tail)...);
			typedef typename detail::concatenate<
				typename std::decay<Head>::type::length_type,
				typename decltype(tail_elements)::length_type
			>::type length;
			return detail::make_element<length>([
				SILICIUM_CAPTURE_EXPRESSION(generate_head, std::move(head.generate)),
				SILICIUM_CAPTURE_EXPRESSION(generate_tail_elements, std::move(tail_elements.generate))
				] (sink<char, success> &destination)
			{
				generate_head(destination);
				generate_tail_elements(destination);
			});
		}

		namespace detail
		{
			template <class A, class B, class C, class D>
			auto operator + (element<A, B> &&left, element<C, D> &&right)
			{
				return sequence(std::move(left), std::move(right));
			}
		}

		template <class ContiguousContainer, class A, class B>
		ContiguousContainer generate(detail::element<A, B> const &tree)
		{
			ContiguousContainer generated;
			auto sink = Sink<char, success>::erase(make_container_sink(generated));
			tree.generate(sink);
			return generated;
		}
	}
}

#endif
<commit_msg>more workarounds for Visual C++ 2013 (does not compile yet)<commit_after>#ifndef SILICIUM_HTML_TREE_HPP
#define SILICIUM_HTML_TREE_HPP

#include <silicium/html/generator.hpp>
#include <silicium/sink/iterator_sink.hpp>
#include <silicium/trait.hpp>

namespace Si
{
	namespace html
	{
		template <std::size_t Length>
		struct exact_length : std::integral_constant<std::size_t, Length>
		{
		};

		template <std::size_t Length>
		struct min_length : std::integral_constant<std::size_t, Length>
		{
		};

		namespace detail
		{
			template <class FirstLength, class SecondLength>
			struct concatenate;

			template <std::size_t FirstLength, std::size_t SecondLength>
			struct concatenate<exact_length<FirstLength>, exact_length<SecondLength>>
			{
				typedef exact_length<FirstLength + SecondLength> type;
			};

			template <std::size_t FirstLength, std::size_t SecondLength>
			struct concatenate<min_length<FirstLength>, exact_length<SecondLength>>
			{
				typedef min_length<FirstLength + SecondLength> type;
			};

			template <std::size_t FirstLength, std::size_t SecondLength>
			struct concatenate<exact_length<FirstLength>, min_length<SecondLength>>
			{
				typedef min_length<FirstLength + SecondLength> type;
			};

			template <std::size_t FirstLength, std::size_t SecondLength>
			struct concatenate<min_length<FirstLength>, min_length<SecondLength>>
			{
				typedef min_length<FirstLength + SecondLength> type;
			};

			template <class ContentGenerator, class Length>
			struct element
			{
				typedef Length length_type;
				ContentGenerator generate;
			};

			template <class Length, class ContentGenerator>
			auto make_element(ContentGenerator &&generate)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				-> element<typename std::decay<ContentGenerator>::type, Length>
#endif
			{
				return element<typename std::decay<ContentGenerator>::type, Length>{std::forward<ContentGenerator>(generate)};
			}
		}

		typedef sink<char, success> destination_sink;

		template <class Length = min_length<0>>
		SILICIUM_TRAIT_WITH_TYPEDEFS(
			Element,
			typedef Length length_type;
			,
			((generate, (1, (destination_sink &)), void, const))
		)

		template <class Length, class ContentGenerator>
		auto dynamic(ContentGenerator &&generate)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> decltype(detail::make_element<Length>(std::forward<ContentGenerator>(generate)))
#endif
		{
			return detail::make_element<Length>(std::forward<ContentGenerator>(generate));
		}

		template <std::size_t Length>
		auto raw(char const (&content)[Length])
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> detail::element<exact_length<Length - 1>, std::function<void(sink<char, success> &)>>
#endif
		{
			return dynamic<exact_length<Length - 1>>(
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				std::function<void(sink<char, success> &)>
#endif
				([&content](sink<char, success> &destination)
			{
				Si::append(destination, content);
			}));
		}

		template <std::size_t NameLength, class Attributes, class Element, class ResultLength = typename detail::concatenate<
			typename std::decay<Element>::type::length_type,
			typename detail::concatenate<
				typename std::decay<Attributes>::type::length_type,
				exact_length<1 + (NameLength - 1) + 1 + 2 + (NameLength - 1) + 1>
			>::type
		>::type>
		auto tag(char const (&name)[NameLength], Attributes &&attributes, Element &&content)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> detail::element<ResultLength, std::function<void(sink<char, success> &)>>
#endif
		{
			return detail::make_element<ResultLength>(
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				std::function<void(sink<char, success> &)>
#endif
				([
					&name,
					SILICIUM_CAPTURE_EXPRESSION(generate_content, std::move(content.generate)),
					SILICIUM_CAPTURE_EXPRESSION(attributes, std::forward<Attributes>(attributes))
				] (sink<char, success> &destination)
				{
					html::open_attributed_element(destination, name);
					attributes.generate(destination);
					html::finish_attributes(destination);
					generate_content(destination);
					html::close_element(destination, name);
				})
			);
		}

		template <std::size_t NameLength, class Attributes, class ResultLength = typename detail::concatenate<
			min_length<1 + (NameLength - 1) + 2>,
			typename std::decay<Attributes>::type::length_type
		>::type>
		auto tag(char const (&name)[NameLength], Attributes &&attributes, empty_t)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> detail::element<ResultLength, std::function<void(sink<char, success> &)>>
#endif
		{
			return detail::make_element<ResultLength>(
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				std::function<void(sink<char, success> &)>
#endif
				([
					&name,
					SILICIUM_CAPTURE_EXPRESSION(attributes, std::forward<Attributes>(attributes))
				] (sink<char, success> &destination)
				{
					html::open_attributed_element(destination, name);
					attributes.generate(destination);
					finish_attributes_of_unpaired_tag(destination);
				})
			);
		}

		namespace detail
		{
			void no_attributes(sink<char, success> &)
			{
			}
		}

		template <std::size_t NameLength, class Element>
		auto tag(char const (&name)[NameLength], Element &&content)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> decltype(tag(name, detail::make_element<exact_length<0>>(&detail::no_attributes), std::forward<Element>(content)))
#endif
		{
			return tag(name, detail::make_element<exact_length<0>>(&detail::no_attributes), std::forward<Element>(content));
		}

		namespace detail
		{
			static BOOST_CONSTEXPR_OR_CONST std::size_t space = 1;
			static BOOST_CONSTEXPR_OR_CONST std::size_t assign = 1;
			static BOOST_CONSTEXPR_OR_CONST std::size_t quote = 1;
		}

		template <
			std::size_t KeyLength,
			std::size_t ValueLength,
			std::size_t ResultLength = detail::space + (KeyLength - 1) + detail::assign + detail::quote + (ValueLength - 1) + detail::quote
		>
		auto attribute(char const (&key)[KeyLength], char const (&value)[ValueLength])
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> detail::element<min_length<ResultLength>, std::function<void(sink<char, success> &)>>
#endif
		{
			return detail::make_element<min_length<ResultLength>>(
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				std::function<void(sink<char, success> &)>
#endif
				([&key, &value](sink<char, success> &destination)
			{
				add_attribute(destination, key, value);
			}));
		}

		template <std::size_t Length>
		auto text(char const (&content)[Length])
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> detail::element<min_length<Length - 1>, std::function<void(sink<char, success> &)>>
#endif
		{
			return detail::make_element<min_length<Length - 1>>(
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				std::function<void(sink<char, success> &)>
#endif
				([&content](sink<char, success> &destination)
				{
					html::write_string(destination, content);
				})
			);
		}

		namespace detail
		{
			void no_content(sink<char, success> &)
			{
			}
		}

		auto sequence()
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> decltype(detail::make_element<exact_length<0>>(&detail::no_content))
#endif
		{
			return detail::make_element<exact_length<0>>(&detail::no_content);
		}

		template <class Head, class ...Tail>
		auto sequence(Head &&head, Tail &&...tail)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
			-> detail::element<min_length<0>, std::function<void(sink<char, success> &)>>
#endif
		{
			auto tail_elements = sequence(std::forward<Tail>(tail)...);
			return detail::make_element<
#if SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				typename detail::concatenate<
					typename std::decay<Head>::type::length_type,
					typename decltype(tail_elements)::length_type
				>::type
#else
				min_length<0>
#endif
			>(
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				std::function<void(sink<char, success> &)>
#endif
				([
					SILICIUM_CAPTURE_EXPRESSION(generate_head, std::move(head.generate)),
					SILICIUM_CAPTURE_EXPRESSION(generate_tail_elements, std::move(tail_elements.generate))
				](sink<char, success> &destination)
				{
					generate_head(destination);
					generate_tail_elements(destination);
				})
			);
		}

		namespace detail
		{
			template <class A, class B, class C, class D>
			auto operator + (element<A, B> &&left, element<C, D> &&right)
#if !SILICIUM_COMPILER_HAS_AUTO_RETURN_TYPE
				-> decltype(sequence(std::move(left), std::move(right)))
#endif
			{
				return sequence(std::move(left), std::move(right));
			}
		}

		template <class ContiguousContainer, class A, class B>
		ContiguousContainer generate(detail::element<A, B> const &tree)
		{
			ContiguousContainer generated;
			auto sink = Sink<char, success>::erase(make_container_sink(generated));
			tree.generate(sink);
			return generated;
		}
	}
}

#endif
<|endoftext|>