<commit_before>/*
 * PrimeNumberFinder.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2010 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#include "PrimeNumberFinder.h"
#include "utils/cpuid.h"
#include "pmath.h"

#include <stdint.h>
#include <stdexcept>
#include <iostream>
#include <cstdlib>
#include <cassert>

namespace {
  const uint32_t END = ~0u;
  const uint32_t BYTE_SIZE = 256;
}

const uint32_t PrimeNumberFinder::nextBitValue_[NUMBERS_PER_BYTE] = { 0,
     0, 0, 0, 0,  0, 0,
    11, 0, 0, 0, 13, 0,
    17, 0, 0, 0, 19, 0,
    23, 0, 0, 0, 29, 0,
     0, 0, 0, 0, 31 };

PrimeNumberFinder::PrimeNumberFinder(uint64_t startNumber, uint64_t stopNumber,
    uint32_t sieveSize, ResetSieve* resetSieve, Results* results,
    uint32_t flags) :
  SieveOfEratosthenes(startNumber, stopNumber, sieveSize, resetSieve), flags_(
      flags), isPOPCNTSupported_(utils::isPOPCNTSupported()), primeByteCounts_(
      NULL), primeBitValues_(NULL), results_(results), status_(0) {
  if (results_ == NULL && (flags_ & RESULTS_FLAGS))
    throw std::logic_error("PrimeNumberFinder: cannot use results_ (is NULL).");
  this->initLookupTables();
}

PrimeNumberFinder::~PrimeNumberFinder() {
  if (primeByteCounts_ != NULL) {
    for (uint32_t i = 0; i < 7; i++) {
      if (primeByteCounts_[i] != NULL)
        delete[] primeByteCounts_[i];
    }
    delete[] primeByteCounts_;
  }
  if (primeBitValues_ != NULL) {
    for (uint32_t i = 0; i < BYTE_SIZE; i++) {
      delete[] primeBitValues_[i];
    }
    delete[] primeBitValues_;
  }
}

/**
 * Initialize lookup tables needed to count and print primes.
 */
void PrimeNumberFinder::initLookupTables() {
  // bits and bitmasks representing the prime numbers and k-tuplets
  // within a byte of the sieve_ array
  const uint32_t bitmasks[7][9] = { { 0x01, 0x02, 0x04, 0x08, 0x10,
        0x20, 0x40, 0x80, END }, // prime numbers
      { 0x06, 0x18, 0xc0, END }, // twin primes
      { 0x07, 0x0e, 0x1c, 0x38, END }, // prime triplets
      { 0x1e, END },            // prime quadruplets
      { 0x1f, 0x3e, END },      // prime quintuplets
      { 0x3f, END },            // prime sextuplets
      { 0xfe, END } };          // prime septuplets

  if (flags_ & COUNT_FLAGS) {
    primeByteCounts_ = new uint32_t*[7];
    for (uint32_t i = 0; i < 7; i++) {
      if ((flags_  & (COUNT_PRIMES << i)) == 0)
        primeByteCounts_[i] = NULL;
      else {
        primeByteCounts_[i] = new uint32_t[BYTE_SIZE];
        // save the count of bitmasks within each byte value
        for (uint32_t j = 0; j < BYTE_SIZE; j++) {
          uint32_t bitmaskCount = 0;
          for (const uint32_t* b = bitmasks[i]; *b != END; b++) {
            if ((j & *b) == *b)
              bitmaskCount++;
          }
          primeByteCounts_[i][j] = bitmaskCount;
        }
      }
    }
  }
  if (flags_ & PRINT_FLAGS) {
    uint32_t index = 0;
    for (uint32_t i = PRINT_PRIMES; (i & flags_) == 0; i <<= 1)
      index++;
    primeBitValues_ = new uint32_t*[BYTE_SIZE];
    // generate the bitValues for each byte value
    for (uint32_t i = 0; i < BYTE_SIZE; i++) {
      primeBitValues_[i] = new uint32_t[9];
      uint32_t bitmaskCount = 0;
      // save the bitValues of the current byte value
      for (const uint32_t* b = bitmasks[index]; *b != END; b++) {
        if ((i & *b) == *b) {
          primeBitValues_[i][bitmaskCount] = bitValues_[ntz(*b)];
          bitmaskCount++;
        }
      }
      primeBitValues_[i][bitmaskCount] = END;
    }
  }
}

/**
 * Count the prime numbers and prime k-tuplets of the current
 * sieve round.
 */
void PrimeNumberFinder::count(const uint8_t* sieve, uint32_t sieveSize) {
  // count prime numbers
  if (flags_ & COUNT_PRIMES) {
    uint32_t primeCount = 0;
    uint32_t i = 0;
#if defined(POPCNT64)
    // count bits using the SSE 4.2 POPCNT instruction
    if (isPOPCNTSupported_) {
      uint32_t size = sieveSize >> 3;
      for (; i < size; i++)
      primeCount += POPCNT64(reinterpret_cast<const uint64_t*>(sieve)[i]);
      i = sieveSize - (sieveSize & 7);
    }
#endif
    // count bits using lookup table
    for (; i < sieveSize; i++)
      primeCount += primeByteCounts_[0][sieve[i]];
    results_->counts[0] += primeCount;
  }
  // count prime k-tuplets
  for (uint32_t i = 1; i < results_->COUNTS_SIZE; i++) {
    if (flags_  & (COUNT_PRIMES << i)) {
      uint32_t kTupletCount = 0;
      for (uint32_t j = 0; j < sieveSize; j++) {
        kTupletCount += primeByteCounts_[i][sieve[j]];
      }
      results_->counts[i] += kTupletCount;
    }
  }
}

/**
 * Print the status (in percents) of the sieving process
 * to the standard output.
 */
void PrimeNumberFinder::status(uint32_t sieveSize) {
  uint64_t upperBound = this->getLowerBound() + (sieveSize - 1)
      * NUMBERS_PER_BYTE;
  float status = 100.0f * (1.0f -
      static_cast<float> (this->getStopNumber() - upperBound) /
      static_cast<float> (this->getStopNumber() - this->getStartNumber()));
  if (flags_ & STORE_STATUS)
    results_->status = status;
  if (flags_ & PRINT_STATUS) {
    uint32_t floorStatus = static_cast<uint32_t> (status);
    if (status_ < floorStatus) {
      status_ = floorStatus;
      std::cout << '\r' << status_ << '%' << std::flush;
    }
  }
}

/**
 * Print the prime numbers or k-tuplets of the current sieve
 * round to the standard output.
 */
void PrimeNumberFinder::print(const uint8_t* sieve, uint32_t sieveSize) {
  uint64_t byteValue = this->getLowerBound();
  for (uint32_t i = 0; i < sieveSize; i++) {
    for (uint32_t* bitValue = primeBitValues_[sieve[i]]; *bitValue != END; bitValue++) {
      if (flags_ & PRINT_PRIMES)
        // print the current prime number
        std::cout << byteValue + *bitValue << std::endl;
      else {
        // print the current k-tuplet
        std::cout << "(";
        uint32_t v = *bitValue;
        for (uint32_t j = PRINT_PRIMES; (j & flags_) == 0; j <<= 1) {
          std::cout << byteValue + v << ", ";
          v = nextBitValue_[v];
        }
        std::cout << byteValue + v << ")" << std::endl;
      }
    }
    byteValue += NUMBERS_PER_BYTE;
  }
}

void PrimeNumberFinder::analyseSieve(const uint8_t* sieve,
    uint32_t sieveSize) {
  if (flags_ & COUNT_FLAGS)
    this->count(sieve, sieveSize);
  if (flags_ & STATUS_FLAGS)
    this->status(sieveSize);
  if (flags_ & PRINT_FLAGS)
    this->print(sieve, sieveSize);
}
<commit_msg>use of ostringstream kTuplet to avoid premature flush of std::cout<commit_after>/*
 * PrimeNumberFinder.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2010 Kim Walisch, <kim.walisch@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#include "PrimeNumberFinder.h"
#include "utils/cpuid.h"
#include "pmath.h"

#include <stdint.h>
#include <stdexcept>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <cassert>

namespace {
  const uint32_t END = ~0u;
  const uint32_t BYTE_SIZE = 256;
}

const uint32_t PrimeNumberFinder::nextBitValue_[NUMBERS_PER_BYTE] = { 0,
     0, 0, 0, 0,  0, 0,
    11, 0, 0, 0, 13, 0,
    17, 0, 0, 0, 19, 0,
    23, 0, 0, 0, 29, 0,
     0, 0, 0, 0, 31 };

PrimeNumberFinder::PrimeNumberFinder(uint64_t startNumber, uint64_t stopNumber,
    uint32_t sieveSize, ResetSieve* resetSieve, Results* results,
    uint32_t flags) :
  SieveOfEratosthenes(startNumber, stopNumber, sieveSize, resetSieve), flags_(
      flags), isPOPCNTSupported_(utils::isPOPCNTSupported()), primeByteCounts_(
      NULL), primeBitValues_(NULL), results_(results), status_(0) {
  if (results_ == NULL && (flags_ & RESULTS_FLAGS))
    throw std::logic_error("PrimeNumberFinder: cannot use results_ (is NULL).");
  this->initLookupTables();
}

PrimeNumberFinder::~PrimeNumberFinder() {
  if (primeByteCounts_ != NULL) {
    for (uint32_t i = 0; i < 7; i++) {
      if (primeByteCounts_[i] != NULL)
        delete[] primeByteCounts_[i];
    }
    delete[] primeByteCounts_;
  }
  if (primeBitValues_ != NULL) {
    for (uint32_t i = 0; i < BYTE_SIZE; i++) {
      delete[] primeBitValues_[i];
    }
    delete[] primeBitValues_;
  }
}

/**
 * Initialize lookup tables needed to count and print primes.
 */
void PrimeNumberFinder::initLookupTables() {
  // bits and bitmasks representing the prime numbers and k-tuplets
  // within a byte of the sieve_ array
  const uint32_t bitmasks[7][9] = { { 0x01, 0x02, 0x04, 0x08, 0x10,
        0x20, 0x40, 0x80, END }, // prime numbers
      { 0x06, 0x18, 0xc0, END }, // twin primes
      { 0x07, 0x0e, 0x1c, 0x38, END }, // prime triplets
      { 0x1e, END },            // prime quadruplets
      { 0x1f, 0x3e, END },      // prime quintuplets
      { 0x3f, END },            // prime sextuplets
      { 0xfe, END } };          // prime septuplets

  if (flags_ & COUNT_FLAGS) {
    primeByteCounts_ = new uint32_t*[7];
    for (uint32_t i = 0; i < 7; i++) {
      if ((flags_  & (COUNT_PRIMES << i)) == 0)
        primeByteCounts_[i] = NULL;
      else {
        primeByteCounts_[i] = new uint32_t[BYTE_SIZE];
        // save the count of bitmasks within each byte value
        for (uint32_t j = 0; j < BYTE_SIZE; j++) {
          uint32_t bitmaskCount = 0;
          for (const uint32_t* b = bitmasks[i]; *b != END; b++) {
            if ((j & *b) == *b)
              bitmaskCount++;
          }
          primeByteCounts_[i][j] = bitmaskCount;
        }
      }
    }
  }
  if (flags_ & PRINT_FLAGS) {
    uint32_t index = 0;
    for (uint32_t i = PRINT_PRIMES; (i & flags_) == 0; i <<= 1)
      index++;
    primeBitValues_ = new uint32_t*[BYTE_SIZE];
    // generate the bitValues for each byte value
    for (uint32_t i = 0; i < BYTE_SIZE; i++) {
      primeBitValues_[i] = new uint32_t[9];
      uint32_t bitmaskCount = 0;
      // save the bitValues of the current byte value
      for (const uint32_t* b = bitmasks[index]; *b != END; b++) {
        if ((i & *b) == *b) {
          primeBitValues_[i][bitmaskCount] = bitValues_[ntz(*b)];
          bitmaskCount++;
        }
      }
      primeBitValues_[i][bitmaskCount] = END;
    }
  }
}

/**
 * Count the prime numbers and prime k-tuplets of the current
 * sieve round.
 */
void PrimeNumberFinder::count(const uint8_t* sieve, uint32_t sieveSize) {
  // count prime numbers
  if (flags_ & COUNT_PRIMES) {
    uint32_t primeCount = 0;
    uint32_t i = 0;
#if defined(POPCNT64)
    // count bits using the SSE 4.2 POPCNT instruction
    if (isPOPCNTSupported_) {
      uint32_t size = sieveSize >> 3;
      for (; i < size; i++)
      primeCount += POPCNT64(reinterpret_cast<const uint64_t*>(sieve)[i]);
      i = sieveSize - (sieveSize & 7);
    }
#endif
    // count bits using lookup table
    for (; i < sieveSize; i++)
      primeCount += primeByteCounts_[0][sieve[i]];
    results_->counts[0] += primeCount;
  }
  // count prime k-tuplets
  for (uint32_t i = 1; i < results_->COUNTS_SIZE; i++) {
    if (flags_  & (COUNT_PRIMES << i)) {
      uint32_t kTupletCount = 0;
      for (uint32_t j = 0; j < sieveSize; j++) {
        kTupletCount += primeByteCounts_[i][sieve[j]];
      }
      results_->counts[i] += kTupletCount;
    }
  }
}

/**
 * Print the status (in percents) of the sieving process
 * to the standard output.
 */
void PrimeNumberFinder::status(uint32_t sieveSize) {
  uint64_t upperBound = this->getLowerBound() + (sieveSize - 1)
      * NUMBERS_PER_BYTE;
  float status = 100.0f * (1.0f -
      static_cast<float> (this->getStopNumber() - upperBound) /
      static_cast<float> (this->getStopNumber() - this->getStartNumber()));
  if (flags_ & STORE_STATUS)
    results_->status = status;
  if (flags_ & PRINT_STATUS) {
    uint32_t floorStatus = static_cast<uint32_t> (status);
    if (status_ < floorStatus) {
      status_ = floorStatus;
      std::cout << '\r' << status_ << '%' << std::flush;
    }
  }
}

/**
 * Print the prime numbers or prime k-tuplets of the current
 * sieve round to the standard output.
 */
void PrimeNumberFinder::print(const uint8_t* sieve, uint32_t sieveSize) {
  uint64_t byteValue = this->getLowerBound();
  for (uint32_t i = 0; i < sieveSize; i++) {
    for (uint32_t* bitValue = primeBitValues_[sieve[i]]; *bitValue != END; bitValue++) {
      if (flags_ & PRINT_PRIMES)
        // print the current prime number
        std::cout << byteValue + *bitValue << std::endl;
      else {
        // print the current prime k-tuplet
        std::ostringstream kTuplet;
        kTuplet << "(";
        uint32_t v = *bitValue;
        for (uint32_t j = PRINT_PRIMES; (j & flags_) == 0; j <<= 1) {
          kTuplet << byteValue + v << ", ";
          v = nextBitValue_[v];
        }
        kTuplet << byteValue + v << ")";
        std::cout << kTuplet.str() << std::endl;
      }
    }
    byteValue += NUMBERS_PER_BYTE;
  }
}

void PrimeNumberFinder::analyseSieve(const uint8_t* sieve,
    uint32_t sieveSize) {
  if (flags_ & COUNT_FLAGS)
    this->count(sieve, sieveSize);
  if (flags_ & STATUS_FLAGS)
    this->status(sieveSize);
  if (flags_ & PRINT_FLAGS)
    this->print(sieve, sieveSize);
}
<|endoftext|>


<commit_before>/*
 * OXT - OS eXtensions for boosT
 * Provides important functionality necessary for writing robust server software.
 *
 * Copyright (c) 2010-2017 Phusion Holding B.V.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#ifndef _OXT_MACROS_HPP_
#define _OXT_MACROS_HPP_

/**
 * Specialized macros.
 *
 * These macros provide more specialized features which are not needed
 * so often by application programmers.
 */

#define OXT_GCC_VERSION (__GNUC__ * 10000 \
                           + __GNUC_MINOR__ * 100 \
                           + __GNUC_PATCHLEVEL__)

#if (defined(__GNUC__) && (__GNUC__ > 2)) || defined(IN_DOXYGEN)
	/**
	 * Indicate that the given expression is likely to be true.
	 * This allows the CPU to better perform branch prediction.
	 */
	#define OXT_LIKELY(expr) __builtin_expect((expr), 1)

	/**
	 * Indicate that the given expression is likely to be false.
	 * This allows the CPU to better perform branch prediction.
	 */
	#define OXT_UNLIKELY(expr) __builtin_expect((expr), 0)

	/**
	 * Force inlining of the given function.
	 */
	#define OXT_FORCE_INLINE __attribute__((always_inline))

	#if __GNUC__ >= 4
		#define OXT_RESTRICT __restrict__
	#else
		#define OXT_RESTRICT
	#endif
	#ifndef restrict
		/**
		 * The C99 'restrict' keyword, now usable in C++.
		 */
		#define restrict OXT_RESTRICT
	#endif
	#ifndef restrict_ref
		/**
		 * The C99 'restrict' keyword, for use with C++ references.
		 * On compilers that support 'restrict' in C++ but not on
		 * references, this macro does nothing.
		 */
		#define restrict_ref OXT_RESTRICT
	#endif
#else
	#define OXT_LIKELY(expr) expr
	#define OXT_UNLIKELY(expr) expr
	#define OXT_FORCE_INLINE
	#define restrict
	#define restrict_ref
#endif

/*
 * GCC supports the __thread keyword on x86 since version 3.3, but versions earlier
 * than 4.1.2 have bugs (http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html).
 *
 * FreeBSD 5 supports the __thread keyword, and everything works fine in
 * micro-tests, but in mod_passenger the thread-local variables are initialized
 * to unaligned addresses for some weird reason, thereby causing bus errors.
 *
 * GCC on OpenBSD supports __thread, but any access to such a variable
 * results in a segfault.
 *
 * Solaris does support __thread, but often it's not compiled into default GCC
 * packages (not to mention it's not available for Sparc). Playing it safe...
 *
 * On MacOS X, neither gcc nor llvm-gcc support the __thread keyword, but Clang
 * does. It works on at least clang >= 3.0.
 */
#ifndef PASSENGER_DISABLE_THREAD_LOCAL_STORAGE
	#if defined(__APPLE__)
		#if defined(__clang__) && __clang_major__ >= 3
			#define OXT_THREAD_LOCAL_KEYWORD_SUPPORTED
		#endif
	#elif defined(__GNUC__) && OXT_GCC_VERSION >= 40102
		#if !defined(__SOLARIS__) && !defined(__OpenBSD__)
			#define OXT_THREAD_LOCAL_KEYWORD_SUPPORTED
		#endif
	#endif
#endif

#endif /* _OXT_MACROS_HPP_ */
<commit_msg>oxt: add the OXT_PURE macro for marking pure functions<commit_after>/*
 * OXT - OS eXtensions for boosT
 * Provides important functionality necessary for writing robust server software.
 *
 * Copyright (c) 2010-2017 Phusion Holding B.V.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#ifndef _OXT_MACROS_HPP_
#define _OXT_MACROS_HPP_

/**
 * Specialized macros.
 *
 * These macros provide more specialized features which are not needed
 * so often by application programmers.
 */

#define OXT_GCC_VERSION (__GNUC__ * 10000 \
                           + __GNUC_MINOR__ * 100 \
                           + __GNUC_PATCHLEVEL__)

#if (defined(__GNUC__) && (__GNUC__ > 2)) || defined(IN_DOXYGEN)
	/**
	 * Indicate that the given expression is likely to be true.
	 * This allows the CPU to better perform branch prediction.
	 */
	#define OXT_LIKELY(expr) __builtin_expect((expr), 1)

	/**
	 * Indicate that the given expression is likely to be false.
	 * This allows the CPU to better perform branch prediction.
	 */
	#define OXT_UNLIKELY(expr) __builtin_expect((expr), 0)

	/**
	 * Force inlining of the given function.
	 */
	#define OXT_FORCE_INLINE __attribute__((always_inline))

	#define OXT_PURE __attribute__((pure))

	#if __GNUC__ >= 4
		#define OXT_RESTRICT __restrict__
	#else
		#define OXT_RESTRICT
	#endif
	#ifndef restrict
		/**
		 * The C99 'restrict' keyword, now usable in C++.
		 */
		#define restrict OXT_RESTRICT
	#endif
	#ifndef restrict_ref
		/**
		 * The C99 'restrict' keyword, for use with C++ references.
		 * On compilers that support 'restrict' in C++ but not on
		 * references, this macro does nothing.
		 */
		#define restrict_ref OXT_RESTRICT
	#endif
#else
	#define OXT_LIKELY(expr) expr
	#define OXT_UNLIKELY(expr) expr
	#define OXT_FORCE_INLINE
	#define OXT_PURE
	#define restrict
	#define restrict_ref
#endif

/*
 * GCC supports the __thread keyword on x86 since version 3.3, but versions earlier
 * than 4.1.2 have bugs (http://gcc.gnu.org/ml/gcc-bugs/2006-09/msg02275.html).
 *
 * FreeBSD 5 supports the __thread keyword, and everything works fine in
 * micro-tests, but in mod_passenger the thread-local variables are initialized
 * to unaligned addresses for some weird reason, thereby causing bus errors.
 *
 * GCC on OpenBSD supports __thread, but any access to such a variable
 * results in a segfault.
 *
 * Solaris does support __thread, but often it's not compiled into default GCC
 * packages (not to mention it's not available for Sparc). Playing it safe...
 *
 * On MacOS X, neither gcc nor llvm-gcc support the __thread keyword, but Clang
 * does. It works on at least clang >= 3.0.
 */
#ifndef PASSENGER_DISABLE_THREAD_LOCAL_STORAGE
	#if defined(__APPLE__)
		#if defined(__clang__) && __clang_major__ >= 3
			#define OXT_THREAD_LOCAL_KEYWORD_SUPPORTED
		#endif
	#elif defined(__GNUC__) && OXT_GCC_VERSION >= 40102
		#if !defined(__SOLARIS__) && !defined(__OpenBSD__)
			#define OXT_THREAD_LOCAL_KEYWORD_SUPPORTED
		#endif
	#endif
#endif

#endif /* _OXT_MACROS_HPP_ */
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "sampleaccumulationbuffer.h"

// appleseed.renderer headers.
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/rendering/generic/developedpixelbuffer.h"
#include "renderer/kernel/shading/shadingresult.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/tile.h"

// Standard headers.
#include <cassert>

using namespace foundation;

namespace renderer
{

SampleAccumulationBuffer::SampleAccumulationBuffer(
    const size_t            width,
    const size_t            height,
    const size_t            aov_count)
  : m_width(width)
  , m_height(height)
  , m_aov_count(aov_count)
  , m_channel_count(1 + 4 + aov_count * 3)
{
    m_buffer.resize(m_width * m_height * m_channel_count, 0.0f);
}

size_t SampleAccumulationBuffer::get_width() const
{
    return m_width;
}

size_t SampleAccumulationBuffer::get_height() const
{
    return m_height;
}

void SampleAccumulationBuffer::add(
    const size_t            x,
    const size_t            y,
    const ShadingResult&    sample,
    const float             weight)
{
    assert(x < m_width);
    assert(y < m_height);
    assert(sample.m_color_space == ColorSpaceLinearRGB);
    assert(sample.m_aovs.size() == m_aov_count);

    float* ptr = &m_buffer[(y * m_width + x) * m_channel_count];

    *ptr++ += weight;

    *ptr++ += sample.m_alpha[0] * weight;

    *ptr++ += sample.m_color[0] * weight;
    *ptr++ += sample.m_color[1] * weight;
    *ptr++ += sample.m_color[2] * weight;

    for (size_t i = 0; i < m_aov_count; ++i)
    {
        *ptr++ += sample.m_aovs[i][0] * weight;
        *ptr++ += sample.m_aovs[i][1] * weight;
        *ptr++ += sample.m_aovs[i][2] * weight;
    }
}

void SampleAccumulationBuffer::develop_pixel(
    const size_t            x,
    const size_t            y,
    DevelopedPixelBuffer&   pixel_buffer) const
{
    assert(x < m_width);
    assert(y < m_height);

    const float* ptr = &m_buffer[(y * m_width + x) * m_channel_count];

    const float weight = *ptr++;
    const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

    const float alpha = *ptr++;

    const Color4f color(ptr[0], ptr[1], ptr[2], alpha);
    pixel_buffer.set_pixel_color(x, y, color * rcp_weight);
    ptr += 3;

    for (size_t i = 0; i < m_aov_count; ++i)
    {
        const Color3f aov(ptr[0], ptr[1], ptr[2]);
        pixel_buffer.set_pixel_aov(x, y, i, aov * rcp_weight);
        ptr += 3;
    }
}

void SampleAccumulationBuffer::develop_to_tile_premult_alpha(
    const AABB2u&           bbox,
    Tile&                   tile,
    TileStack&              aov_tiles) const
{
    for (size_t y = bbox.min.y; y <= bbox.max.y; ++y)
    {
        for (size_t x = bbox.min.x; x <= bbox.max.x; ++x)
        {
            const float* ptr = &m_buffer[(y * m_width + x) * m_channel_count];

            const float weight = *ptr++;
            const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

            const float alpha = *ptr++;

            const Color4f color(ptr[0], ptr[1], ptr[2], alpha);
            tile.set_pixel(x, y, color * rcp_weight);
            ptr += 3;

            for (size_t i = 0; i < m_aov_count; ++i)
            {
                const Color4f aov(ptr[0], ptr[1], ptr[2], alpha);
                aov_tiles.set_pixel(x, y, i, aov * rcp_weight);
                ptr += 3;
            }
        }
    }
}

void SampleAccumulationBuffer::develop_to_tile_premult_alpha(
    Tile&                   tile,
    TileStack&              aov_tiles) const
{
    develop_to_tile_premult_alpha(
        AABB2u(Vector2u(0, 0), Vector2u(m_width - 1, m_height - 1)),
        tile,
        aov_tiles);
}

void SampleAccumulationBuffer::develop_to_tile_straight_alpha(
    const AABB2u&           bbox,
    Tile&                   tile,
    TileStack&              aov_tiles) const
{
    for (size_t y = bbox.min.y; y <= bbox.max.y; ++y)
    {
        for (size_t x = bbox.min.x; x <= bbox.max.x; ++x)
        {
            const float* ptr = &m_buffer[(y * m_width + x) * m_channel_count];

            const float weight = *ptr++;
            const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

            const float alpha = *ptr++;
            const float rcp_alpha = alpha == 0.0f ? 0.0f : 1.0f / alpha;

            Color4f color(ptr[0], ptr[1], ptr[2], alpha);
            color.rgb() *= rcp_alpha;
            color.a *= rcp_weight;
            tile.set_pixel(x, y, color);
            ptr += 3;

            for (size_t i = 0; i < m_aov_count; ++i)
            {
                Color4f aov(ptr[0], ptr[1], ptr[2], alpha);
                aov.rgb() *= rcp_alpha;
                aov.a *= rcp_weight;
                aov_tiles.set_pixel(x, y, i, aov);
                ptr += 3;
            }
        }
    }
}

void SampleAccumulationBuffer::develop_to_tile_straight_alpha(
    Tile&                   tile,
    TileStack&              aov_tiles) const
{
    develop_to_tile_straight_alpha(
        AABB2u(Vector2u(0, 0), Vector2u(m_width - 1, m_height - 1)),
        tile,
        aov_tiles);
}

}   // namespace renderer
<commit_msg>fixed warnings on 64-bit Windows.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz Limited
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "sampleaccumulationbuffer.h"

// appleseed.renderer headers.
#include "renderer/kernel/aov/tilestack.h"
#include "renderer/kernel/rendering/generic/developedpixelbuffer.h"
#include "renderer/kernel/shading/shadingresult.h"

// appleseed.foundation headers.
#include "foundation/image/color.h"
#include "foundation/image/tile.h"

// Standard headers.
#include <cassert>

using namespace foundation;

namespace renderer
{

SampleAccumulationBuffer::SampleAccumulationBuffer(
    const size_t            width,
    const size_t            height,
    const size_t            aov_count)
  : m_width(width)
  , m_height(height)
  , m_aov_count(aov_count)
  , m_channel_count(1 + 4 + aov_count * 3)
{
    m_buffer.resize(m_width * m_height * m_channel_count, 0.0f);
}

size_t SampleAccumulationBuffer::get_width() const
{
    return m_width;
}

size_t SampleAccumulationBuffer::get_height() const
{
    return m_height;
}

void SampleAccumulationBuffer::add(
    const size_t            x,
    const size_t            y,
    const ShadingResult&    sample,
    const float             weight)
{
    assert(x < m_width);
    assert(y < m_height);
    assert(sample.m_color_space == ColorSpaceLinearRGB);
    assert(sample.m_aovs.size() == m_aov_count);

    float* ptr = &m_buffer[(y * m_width + x) * m_channel_count];

    *ptr++ += weight;

    *ptr++ += sample.m_alpha[0] * weight;

    *ptr++ += sample.m_color[0] * weight;
    *ptr++ += sample.m_color[1] * weight;
    *ptr++ += sample.m_color[2] * weight;

    for (size_t i = 0; i < m_aov_count; ++i)
    {
        *ptr++ += sample.m_aovs[i][0] * weight;
        *ptr++ += sample.m_aovs[i][1] * weight;
        *ptr++ += sample.m_aovs[i][2] * weight;
    }
}

void SampleAccumulationBuffer::develop_pixel(
    const size_t            x,
    const size_t            y,
    DevelopedPixelBuffer&   pixel_buffer) const
{
    assert(x < m_width);
    assert(y < m_height);

    const float* ptr = &m_buffer[(y * m_width + x) * m_channel_count];

    const float weight = *ptr++;
    const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

    const float alpha = *ptr++;

    const Color4f color(ptr[0], ptr[1], ptr[2], alpha);
    pixel_buffer.set_pixel_color(static_cast<int>(x), static_cast<int>(y), color * rcp_weight);
    ptr += 3;

    for (size_t i = 0; i < m_aov_count; ++i)
    {
        const Color3f aov(ptr[0], ptr[1], ptr[2]);
        pixel_buffer.set_pixel_aov(static_cast<int>(x), static_cast<int>(y), i, aov * rcp_weight);
        ptr += 3;
    }
}

void SampleAccumulationBuffer::develop_to_tile_premult_alpha(
    const AABB2u&           bbox,
    Tile&                   tile,
    TileStack&              aov_tiles) const
{
    for (size_t y = bbox.min.y; y <= bbox.max.y; ++y)
    {
        for (size_t x = bbox.min.x; x <= bbox.max.x; ++x)
        {
            const float* ptr = &m_buffer[(y * m_width + x) * m_channel_count];

            const float weight = *ptr++;
            const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

            const float alpha = *ptr++;

            const Color4f color(ptr[0], ptr[1], ptr[2], alpha);
            tile.set_pixel(x, y, color * rcp_weight);
            ptr += 3;

            for (size_t i = 0; i < m_aov_count; ++i)
            {
                const Color4f aov(ptr[0], ptr[1], ptr[2], alpha);
                aov_tiles.set_pixel(x, y, i, aov * rcp_weight);
                ptr += 3;
            }
        }
    }
}

void SampleAccumulationBuffer::develop_to_tile_premult_alpha(
    Tile&                   tile,
    TileStack&              aov_tiles) const
{
    develop_to_tile_premult_alpha(
        AABB2u(Vector2u(0, 0), Vector2u(m_width - 1, m_height - 1)),
        tile,
        aov_tiles);
}

void SampleAccumulationBuffer::develop_to_tile_straight_alpha(
    const AABB2u&           bbox,
    Tile&                   tile,
    TileStack&              aov_tiles) const
{
    for (size_t y = bbox.min.y; y <= bbox.max.y; ++y)
    {
        for (size_t x = bbox.min.x; x <= bbox.max.x; ++x)
        {
            const float* ptr = &m_buffer[(y * m_width + x) * m_channel_count];

            const float weight = *ptr++;
            const float rcp_weight = weight == 0.0f ? 0.0f : 1.0f / weight;

            const float alpha = *ptr++;
            const float rcp_alpha = alpha == 0.0f ? 0.0f : 1.0f / alpha;

            Color4f color(ptr[0], ptr[1], ptr[2], alpha);
            color.rgb() *= rcp_alpha;
            color.a *= rcp_weight;
            tile.set_pixel(x, y, color);
            ptr += 3;

            for (size_t i = 0; i < m_aov_count; ++i)
            {
                Color4f aov(ptr[0], ptr[1], ptr[2], alpha);
                aov.rgb() *= rcp_alpha;
                aov.a *= rcp_weight;
                aov_tiles.set_pixel(x, y, i, aov);
                ptr += 3;
            }
        }
    }
}

void SampleAccumulationBuffer::develop_to_tile_straight_alpha(
    Tile&                   tile,
    TileStack&              aov_tiles) const
{
    develop_to_tile_straight_alpha(
        AABB2u(Vector2u(0, 0), Vector2u(m_width - 1, m_height - 1)),
        tile,
        aov_tiles);
}

}   // namespace renderer
<|endoftext|>


<commit_before>// Copyright 2009, Squish Tech, LLC.
#include "node.h"

#include "document.h"
#include "element.h"
#include "attribute.h"
#include "namespace.h"

namespace libxmljs {

v8::Persistent<v8::FunctionTemplate> Node::constructor_template;

v8::Handle<v8::Value>
Node::Doc(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                             \
  assert(node);

  return node->get_doc();
}

v8::Handle<v8::Value>
Node::Namespace(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                             \
  assert(node);

  // #namespace() Get the node's namespace
  if (args.Length() == 0)
    return node->get_namespace();

  if (args[0]->IsNull())
    return node->remove_namespace();

  libxmljs::Namespace *ns = NULL;

  // #namespace(ns) libxml.Namespace object was provided
  // TODO (sprsquish): check that it was actually given a namespace obj
  if (args[0]->IsObject())
    ns = LibXmlObj::Unwrap<libxmljs::Namespace>(args[0]->ToObject());

  // #namespace(href) or #namespace(prefix, href)
  // if the namespace has already been defined on the node, just set it
  if (args[0]->IsString()) {
    v8::String::Utf8Value ns_to_find(args[0]->ToString());
    xmlNs* found_ns = node->find_namespace(*ns_to_find);
    if (found_ns)
      ns = LibXmlObj::Unwrap<libxmljs::Namespace>(
        JsObj::Unwrap<xmlNs>(found_ns));
  }

  // Namespace does not seem to exist, so create it.
  if (!ns) {
    int argc = 3;
    v8::Handle<v8::Value> argv[argc];
    argv[0] = args.This();

    if (args.Length() == 1) {
      argv[1] = v8::Null();
      argv[2] = args[0];
    }
    else {
      argv[1] = args[0];
      argv[2] = args[1];
    }

    v8::Handle<v8::Function> define_namespace =
      Namespace::constructor_template->GetFunction();

    v8::Persistent<v8::Object> new_ns = v8::Persistent<v8::Object>::New(
      define_namespace->Call(args.This(), argc, argv)->ToObject());
    ns = LibXmlObj::Unwrap<libxmljs::Namespace>(new_ns);
  }

  node->set_namespace(ns->xml_obj);

  return node->get_namespace();
}

v8::Handle<v8::Value>
Node::Parent(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                             \
  assert(node);

  return node->get_parent();
}

v8::Handle<v8::Value>
Node::PrevSibling(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                             \
  assert(node);

  return node->get_prev_sibling();
}

v8::Handle<v8::Value>
Node::NextSibling(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                             \
  assert(node);

  return node->get_next_sibling();
}

Node::Node(xmlNode* node) : xml_obj(node) {
  xml_obj->_private = this;
}

Node::~Node() {
  xmlFree(xml_obj);
}

v8::Handle<v8::Value>
Node::get_doc() {
  return JsObj::Unwrap<xmlDoc>(xml_obj->doc);
}

v8::Handle<v8::Value>
Node::remove_namespace() {
  xml_obj->ns = NULL;
  return v8::Null();
}

v8::Handle<v8::Value>
Node::get_namespace() {
  if (!xml_obj->ns)
    return v8::Null();

  if (!xml_obj->ns->_private)
    return Namespace::New(xml_obj->ns);

  return JsObj::Unwrap<xmlNs>(xml_obj->ns);
}

void
Node::set_namespace(xmlNs* ns) {
  xmlSetNs(xml_obj, ns);
}

xmlNs*
Node::find_namespace(const char* search_str) {
  xmlNs* ns = NULL;

  // Find by prefix first
  ns = xmlSearchNs(xml_obj->doc, xml_obj, (const xmlChar*)search_str);

  // Or find by href
  if (!ns)
    ns = xmlSearchNsByHref(xml_obj->doc, xml_obj, (const xmlChar*)search_str);

  return ns;
}

v8::Handle<v8::Value>
Node::get_parent() {
  if (xml_obj->parent)
    return LIBXMLJS_GET_MAYBE_BUILD(Element, xmlNode, xml_obj->parent);

  return LIBXMLJS_GET_MAYBE_BUILD(Document, xmlDoc, xml_obj->doc);
}

v8::Handle<v8::Value>
Node::get_prev_sibling() {
  if (xml_obj->prev)
    return LIBXMLJS_GET_MAYBE_BUILD(Element, xmlNode, xml_obj->prev);

  return v8::Null();
}

v8::Handle<v8::Value>
Node::get_next_sibling() {
  if (xml_obj->next)
    return LIBXMLJS_GET_MAYBE_BUILD(Element, xmlNode, xml_obj->next);

  return v8::Null();
}

void
Node::Initialize(v8::Handle<v8::Object> target) {
  v8::HandleScope scope;
  constructor_template =
    v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
  constructor_template->InstanceTemplate()->SetInternalFieldCount(1);

  LXJS_SET_PROTO_METHOD(constructor_template, "doc", Node::Doc);
  LXJS_SET_PROTO_METHOD(constructor_template, "parent", Node::Parent);
  LXJS_SET_PROTO_METHOD(constructor_template, "namespace", Node::Namespace);
  LXJS_SET_PROTO_METHOD(constructor_template, "prev_sibling", Node::PrevSibling);
  LXJS_SET_PROTO_METHOD(constructor_template, "next_sibling", Node::NextSibling);

  Element::Initialize(target);
  Attribute::Initialize(target);
}
}  // namespace libxmljs
<commit_msg>cpplint node.cc<commit_after>// Copyright 2009, Squish Tech, LLC.
#include "node.h"

#include "document.h"
#include "element.h"
#include "attribute.h"
#include "namespace.h"

namespace libxmljs {

v8::Persistent<v8::FunctionTemplate> Node::constructor_template;

v8::Handle<v8::Value>
Node::Doc(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                \
  assert(node);

  return node->get_doc();
}

v8::Handle<v8::Value>
Node::Namespace(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                \
  assert(node);

  // #namespace() Get the node's namespace
  if (args.Length() == 0)
    return node->get_namespace();

  if (args[0]->IsNull())
    return node->remove_namespace();

  libxmljs::Namespace *ns = NULL;

  // #namespace(ns) libxml.Namespace object was provided
  // TODO(sprsquish): check that it was actually given a namespace obj
  if (args[0]->IsObject())
    ns = LibXmlObj::Unwrap<libxmljs::Namespace>(args[0]->ToObject());

  // #namespace(href) or #namespace(prefix, href)
  // if the namespace has already been defined on the node, just set it
  if (args[0]->IsString()) {
    v8::String::Utf8Value ns_to_find(args[0]->ToString());
    xmlNs* found_ns = node->find_namespace(*ns_to_find);
    if (found_ns)
      ns = LibXmlObj::Unwrap<libxmljs::Namespace>(
        JsObj::Unwrap<xmlNs>(found_ns));
  }

  // Namespace does not seem to exist, so create it.
  if (!ns) {
    int argc = 3;
    v8::Handle<v8::Value> argv[argc];
    argv[0] = args.This();

    if (args.Length() == 1) {
      argv[1] = v8::Null();
      argv[2] = args[0];
    } else {
      argv[1] = args[0];
      argv[2] = args[1];
    }

    v8::Handle<v8::Function> define_namespace =
      Namespace::constructor_template->GetFunction();

    v8::Persistent<v8::Object> new_ns = v8::Persistent<v8::Object>::New(
      define_namespace->Call(args.This(), argc, argv)->ToObject());
    ns = LibXmlObj::Unwrap<libxmljs::Namespace>(new_ns);
  }

  node->set_namespace(ns->xml_obj);

  return node->get_namespace();
}

v8::Handle<v8::Value>
Node::Parent(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                \
  assert(node);

  return node->get_parent();
}

v8::Handle<v8::Value>
Node::PrevSibling(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                \
  assert(node);

  return node->get_prev_sibling();
}

v8::Handle<v8::Value>
Node::NextSibling(const v8::Arguments& args) {
  v8::HandleScope scope;
  Node *node = LibXmlObj::Unwrap<libxmljs::Node>(args.This());                \
  assert(node);

  return node->get_next_sibling();
}

Node::Node(xmlNode* node) : xml_obj(node) {
  xml_obj->_private = this;
}

Node::~Node() {
  xmlFree(xml_obj);
}

v8::Handle<v8::Value>
Node::get_doc() {
  return JsObj::Unwrap<xmlDoc>(xml_obj->doc);
}

v8::Handle<v8::Value>
Node::remove_namespace() {
  xml_obj->ns = NULL;
  return v8::Null();
}

v8::Handle<v8::Value>
Node::get_namespace() {
  if (!xml_obj->ns)
    return v8::Null();

  if (!xml_obj->ns->_private)
    return Namespace::New(xml_obj->ns);

  return JsObj::Unwrap<xmlNs>(xml_obj->ns);
}

void
Node::set_namespace(xmlNs* ns) {
  xmlSetNs(xml_obj, ns);
}

xmlNs*
Node::find_namespace(const char* search_str) {
  xmlNs* ns = NULL;

  // Find by prefix first
  ns = xmlSearchNs(xml_obj->doc, xml_obj, (const xmlChar*)search_str);

  // Or find by href
  if (!ns)
    ns = xmlSearchNsByHref(xml_obj->doc, xml_obj, (const xmlChar*)search_str);

  return ns;
}

v8::Handle<v8::Value>
Node::get_parent() {
  if (xml_obj->parent)
    return LIBXMLJS_GET_MAYBE_BUILD(Element, xmlNode, xml_obj->parent);

  return LIBXMLJS_GET_MAYBE_BUILD(Document, xmlDoc, xml_obj->doc);
}

v8::Handle<v8::Value>
Node::get_prev_sibling() {
  if (xml_obj->prev)
    return LIBXMLJS_GET_MAYBE_BUILD(Element, xmlNode, xml_obj->prev);

  return v8::Null();
}

v8::Handle<v8::Value>
Node::get_next_sibling() {
  if (xml_obj->next)
    return LIBXMLJS_GET_MAYBE_BUILD(Element, xmlNode, xml_obj->next);

  return v8::Null();
}

void
Node::Initialize(v8::Handle<v8::Object> target) {
  v8::HandleScope scope;
  constructor_template =
    v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New());
  constructor_template->InstanceTemplate()->SetInternalFieldCount(1);

  LXJS_SET_PROTO_METHOD(constructor_template,
                        "doc",
                        Node::Doc);

  LXJS_SET_PROTO_METHOD(constructor_template,
                        "parent",
                        Node::Parent);

  LXJS_SET_PROTO_METHOD(constructor_template,
                        "namespace",
                        Node::Namespace);

  LXJS_SET_PROTO_METHOD(constructor_template,
                        "prev_sibling",
                        Node::PrevSibling);

  LXJS_SET_PROTO_METHOD(constructor_template,
                        "next_sibling",
                        Node::NextSibling);

  Element::Initialize(target);
  Attribute::Initialize(target);
}
}  // namespace libxmljs
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_UI_CONNECTED_BUTTONS_HPP
#define RJ_UI_CONNECTED_BUTTONS_HPP

#include "button.hpp"
#include <rectojump/global/common.hpp>
#include <rectojump/global/config_settings.hpp>

namespace rj
{
	template<typename T>
	using btn_ptr = mlk::sptr<T>;

	using base_btn_ptr = btn_ptr<button>;

	class connected_buttons : public sf::Drawable
	{
		std::map<int, base_btn_ptr> m_buttons;
		int m_current_pressed_index{0};
		int m_current_add_index{0};

	public:
		mlk::slot<base_btn_ptr&> on_active_button;
		mlk::slot<base_btn_ptr&> on_inactive_button;

		connected_buttons() = default;

		void update(dur duration)
		{
			for(auto& a : m_buttons)
			{
				// update all buttons
				a.second->update(duration);

				// get current pressed button
				on_inactive_button(a.second);
				if(a.second->is_pressed())
					m_current_pressed_index = a.first;
			}
			// call the custom user settings
			on_active_button(m_buttons[m_current_pressed_index]);
		}

		template<typename Button_Type, typename... Args>
		btn_ptr<Button_Type> add_button(Args&&... args)
		{
			auto ptr(std::make_shared<Button_Type>(std::forward<Args>(args)...));
			m_buttons.emplace(m_current_add_index, ptr);
			++m_current_add_index;
			return ptr;
		}

	private:
		void draw(sf::RenderTarget& target, sf::RenderStates states) const override
		{
			for(auto& a : m_buttons)
				target.draw(*a.second, states);
		}
	};
}

#endif // RJ_UI_CONNECTED_BUTTONS_HPP
<commit_msg>connected_buttons: added get_active_btn()<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_UI_CONNECTED_BUTTONS_HPP
#define RJ_UI_CONNECTED_BUTTONS_HPP

#include "button.hpp"
#include <rectojump/global/common.hpp>

namespace rj
{
	template<typename T>
	using btn_ptr = mlk::sptr<T>;

	using base_btn_ptr = btn_ptr<button>;

	class connected_buttons : public sf::Drawable
	{
		std::map<int, base_btn_ptr> m_buttons;
		int m_current_pressed_index{0};
		int m_current_add_index{0};

	public:
		mlk::slot<base_btn_ptr&> on_active_button;
		mlk::slot<base_btn_ptr&> on_inactive_button;

		connected_buttons() = default;

		void update(dur duration)
		{
			for(auto& a : m_buttons)
			{
				// update all buttons
				a.second->update(duration);

				// get current pressed button
				on_inactive_button(a.second);
				if(a.second->is_pressed())
					m_current_pressed_index = a.first;
			}
			// call the custom user settings
			on_active_button(m_buttons[m_current_pressed_index]);
		}

		template<typename Button_Type, typename... Args>
		btn_ptr<Button_Type> add_button(Args&&... args)
		{
			auto ptr(std::make_shared<Button_Type>(std::forward<Args>(args)...));
			m_buttons.emplace(m_current_add_index, ptr);
			++m_current_add_index;
			return ptr;
		}

		const base_btn_ptr& get_active_btn() const noexcept
		{return m_buttons.at(m_current_pressed_index);}

	private:
		void draw(sf::RenderTarget& target, sf::RenderStates states) const override
		{
			for(auto& a : m_buttons)
				target.draw(*a.second, states);
		}
	};
}

#endif // RJ_UI_CONNECTED_BUTTONS_HPP
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH
#define DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH

#include <dune/gdt/localevaluation/elliptic.hh>

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

template <class DiffusionFactorType, class DiffusionTensorType>
class Elliptic
    : public LocalEvaluation::Codim0Interface<internal::EllipticTraits<DiffusionFactorType, DiffusionTensorType>, 2>
{
public:
  typedef internal::EllipticTraits<DiffusionFactorType, DiffusionTensorType> Traits;

  Elliptic(const DiffusionFactorType& diffusion_factor, const DiffusionTensorType& diffusion_tensor)
    : diffusion_factor_(diffusion_factor)
    , diffusion_tensor_(diffusion_tensor)
  {
  }

  template <class EntityType>
  class LocalfunctionTuple
  {
    typedef typename DiffusionFactorType::LocalfunctionType LocalDiffusionFactorFunctionType;
    typedef typename DiffusionTensorType::LocalfunctionType LocalDiffusionTensorFunctionType;

  public:
    typedef std::tuple<std::shared_ptr<LocalDiffusionFactorFunctionType>,
                       std::shared_ptr<LocalDiffusionTensorFunctionType>> Type;
  }; // class LocalfunctionTuple

  template <class EntityType>
  typename LocalfunctionTuple<EntityType>::Type localFunctions(const EntityType& entity) const
  {
    return std::make_tuple(diffusion_factor_.local_function(entity), diffusion_tensor_.local_function(entity));
  } // ... localFunctions(...)

  /**
   * \brief extracts the local functions and calls the correct order() method
   */
  template <class E, class D, int d, class R, int rT, int rCT, int rA, int rCA>
  size_t order(const typename LocalfunctionTuple<E>::Type& local_functions_tuple,
               const Stuff::LocalfunctionSetInterface<E, D, d, R, rT, rCT>& testBase,
               const Stuff::LocalfunctionSetInterface<E, D, d, R, rA, rCA>& ansatzBase) const
  {
    const auto local_diffusion_factor = std::get<0>(local_functions_tuple);
    const auto local_diffusion_tensor = std::get<1>(local_functions_tuple);
    return order(*local_diffusion_factor, *local_diffusion_tensor, testBase, ansatzBase);
  } // ... order(...)

  template <class E, class D, int d, class R, int rDF, int rCDF, int rDT, int rCDT, int rT, int rCT, int rA, int rCA>
  size_t order(const Stuff::LocalfunctionInterface<E, D, d, R, rDF, rCDF>& local_diffusion_factor,
               const Stuff::LocalfunctionInterface<E, D, d, R, rDT, rCDT>& local_diffusion_tensor,
               const Stuff::LocalfunctionSetInterface<E, D, d, R, rT, rCT>& testBase,
               const Stuff::LocalfunctionSetInterface<E, D, d, R, rA, rCA>& ansatzBase) const
  {
    return local_diffusion_factor.order() + local_diffusion_tensor.order() + std::max(int(testBase.order() - 1), 0)
           + std::max(int(ansatzBase.order() - 1), 0);
  } // ... order(...)

  /**
   * \brief extracts the local functions and calls the correct evaluate() method
   */
  template <class E, class D, int d, class R, int rT, int rCT, int rA, int rCA>
  void evaluate(const typename LocalfunctionTuple<E>::Type& local_functions_tuple,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, rT, rCT>& testBase,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, rA, rCA>& ansatzBase,
                const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret) const
  {
    const auto local_diffusion_factor = std::get<0>(local_functions_tuple);
    const auto local_diffusion_tensor = std::get<1>(local_functions_tuple);
    evaluate(*local_diffusion_factor, *local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

  template <class E, class D, int d, class R, int rDF, int rCDF, int rDT, int rCDT, int rT, int rCT, int rA, int rCA>
  void evaluate(const Stuff::LocalfunctionInterface<E, D, d, R, rDF, rCDF>& /*local_diffusion_factor*/,
                const Stuff::LocalfunctionInterface<E, D, d, R, rDT, rCDT>& /*local_diffusion_tensor*/,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, rT, rCT>& /*testBase*/,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, rA, rCA>& /*ansatzBase*/,
                const Dune::FieldVector<D, d>& /*localPoint*/, Dune::DynamicMatrix<R>& /*ret*/) const
  {
    static_assert(Dune::AlwaysFalse<R>::value, "Not implemented for these dimensions!");
  }

  template <class E, class D, int d, class R, int r>
  void evaluate(const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_factor,
                const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, r, 1>& testBase,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, r, 1>& ansatzBase,
                const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret)
  {
    typedef typename Stuff::LocalfunctionSetInterface<E, D, d, R, r, 1>::JacobianRangeType JacobianRangeType;
    // evaluate local functions
    const auto local_diffusion_factor_value = local_diffusion_factor.evaluate(localPoint);
    const auto local_diffusion_tensor_value = local_diffusion_tensor.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector<JacobianRangeType> testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector<JacobianRangeType> ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        retRow[jj] = local_diffusion_factor_value * local_diffusion_tensor_value
                     * (ansatzGradients[jj][0] * testGradients[ii][0]);
      }
    }
  } // ... evaluate< ..., 1, 1 >(...)

  template <class E, class D, int d, class R>
  void evaluate(const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_factor,
                const Stuff::LocalfunctionInterface<E, D, d, R, 2, 2>& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& testBase,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& ansatzBase,
                const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret)
  {
    evaluate_matrix_valued_(local_diffusion_factor, local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

  template <class E, class D, int d, class R>
  void evaluate(const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_factor,
                const Stuff::LocalfunctionInterface<E, D, d, R, 3, 3>& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& testBase,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& ansatzBase,
                const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret)
  {
    evaluate_matrix_valued_(local_diffusion_factor, local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

private:
  template <class E, class D, int d, class R>
  void evaluate_matrix_valued_(const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_factor,
                               const Stuff::LocalfunctionInterface<E, D, d, R, d, d>& local_diffusion_tensor,
                               const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& testBase,
                               const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& ansatzBase,
                               const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret)
  {
    typedef typename Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>::JacobianRangeType JacobianRangeType;
    // evaluate local functions
    const auto local_diffusion_factor_value = local_diffusion_factor.evaluate(localPoint);
    auto local_diffusion_tensor_value       = local_diffusion_tensor.evaluate(localPoint);
    local_diffusion_tensor_value *= local_diffusion_factor_value[0];
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector<JacobianRangeType> testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector<JacobianRangeType> ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    FieldVector<D, d> product(0.0);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        local_diffusion_tensor_value.mv(ansatzGradients[jj][0], product);
        retRow[jj] = product * testGradients[ii][0];
      }
    }
  } // ... evaluate_matrix_valued_(...)

  const DiffusionFactorType& diffusion_factor_;
  const DiffusionTensorType& diffusion_tensor_;
}; // class LocalElliptic

} // namespace Evaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH
<commit_msg>[localevaluation.elliptic] added missing const in playground<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH
#define DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH

#include <dune/gdt/localevaluation/elliptic.hh>

namespace Dune {
namespace GDT {
namespace LocalEvaluation {

template <class DiffusionFactorType, class DiffusionTensorType>
class Elliptic
    : public LocalEvaluation::Codim0Interface<internal::EllipticTraits<DiffusionFactorType, DiffusionTensorType>, 2>
{
public:
  typedef internal::EllipticTraits<DiffusionFactorType, DiffusionTensorType> Traits;

  Elliptic(const DiffusionFactorType& diffusion_factor, const DiffusionTensorType& diffusion_tensor)
    : diffusion_factor_(diffusion_factor)
    , diffusion_tensor_(diffusion_tensor)
  {
  }

  template <class EntityType>
  class LocalfunctionTuple
  {
    typedef typename DiffusionFactorType::LocalfunctionType LocalDiffusionFactorFunctionType;
    typedef typename DiffusionTensorType::LocalfunctionType LocalDiffusionTensorFunctionType;

  public:
    typedef std::tuple<std::shared_ptr<LocalDiffusionFactorFunctionType>,
                       std::shared_ptr<LocalDiffusionTensorFunctionType>> Type;
  }; // class LocalfunctionTuple

  template <class EntityType>
  typename LocalfunctionTuple<EntityType>::Type localFunctions(const EntityType& entity) const
  {
    return std::make_tuple(diffusion_factor_.local_function(entity), diffusion_tensor_.local_function(entity));
  } // ... localFunctions(...)

  /**
   * \brief extracts the local functions and calls the correct order() method
   */
  template <class E, class D, int d, class R, int rT, int rCT, int rA, int rCA>
  size_t order(const typename LocalfunctionTuple<E>::Type& local_functions_tuple,
               const Stuff::LocalfunctionSetInterface<E, D, d, R, rT, rCT>& testBase,
               const Stuff::LocalfunctionSetInterface<E, D, d, R, rA, rCA>& ansatzBase) const
  {
    const auto local_diffusion_factor = std::get<0>(local_functions_tuple);
    const auto local_diffusion_tensor = std::get<1>(local_functions_tuple);
    return order(*local_diffusion_factor, *local_diffusion_tensor, testBase, ansatzBase);
  } // ... order(...)

  template <class E, class D, int d, class R, int rDF, int rCDF, int rDT, int rCDT, int rT, int rCT, int rA, int rCA>
  size_t order(const Stuff::LocalfunctionInterface<E, D, d, R, rDF, rCDF>& local_diffusion_factor,
               const Stuff::LocalfunctionInterface<E, D, d, R, rDT, rCDT>& local_diffusion_tensor,
               const Stuff::LocalfunctionSetInterface<E, D, d, R, rT, rCT>& testBase,
               const Stuff::LocalfunctionSetInterface<E, D, d, R, rA, rCA>& ansatzBase) const
  {
    return local_diffusion_factor.order() + local_diffusion_tensor.order() + std::max(int(testBase.order() - 1), 0)
           + std::max(int(ansatzBase.order() - 1), 0);
  } // ... order(...)

  /**
   * \brief extracts the local functions and calls the correct evaluate() method
   */
  template <class E, class D, int d, class R, int rT, int rCT, int rA, int rCA>
  void evaluate(const typename LocalfunctionTuple<E>::Type& local_functions_tuple,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, rT, rCT>& testBase,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, rA, rCA>& ansatzBase,
                const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret) const
  {
    const auto local_diffusion_factor = std::get<0>(local_functions_tuple);
    const auto local_diffusion_tensor = std::get<1>(local_functions_tuple);
    evaluate(*local_diffusion_factor, *local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

  template <class E, class D, int d, class R, int rDF, int rCDF, int rDT, int rCDT, int rT, int rCT, int rA, int rCA>
  void evaluate(const Stuff::LocalfunctionInterface<E, D, d, R, rDF, rCDF>& /*local_diffusion_factor*/,
                const Stuff::LocalfunctionInterface<E, D, d, R, rDT, rCDT>& /*local_diffusion_tensor*/,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, rT, rCT>& /*testBase*/,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, rA, rCA>& /*ansatzBase*/,
                const Dune::FieldVector<D, d>& /*localPoint*/, Dune::DynamicMatrix<R>& /*ret*/) const
  {
    static_assert(Dune::AlwaysFalse<R>::value, "Not implemented for these dimensions!");
  }

  template <class E, class D, int d, class R, int r>
  void evaluate(const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_factor,
                const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, r, 1>& testBase,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, r, 1>& ansatzBase,
                const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret) const
  {
    typedef typename Stuff::LocalfunctionSetInterface<E, D, d, R, r, 1>::JacobianRangeType JacobianRangeType;
    // evaluate local functions
    const auto local_diffusion_factor_value = local_diffusion_factor.evaluate(localPoint);
    const auto local_diffusion_tensor_value = local_diffusion_tensor.evaluate(localPoint);
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector<JacobianRangeType> testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector<JacobianRangeType> ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        retRow[jj] = local_diffusion_factor_value * local_diffusion_tensor_value
                     * (ansatzGradients[jj][0] * testGradients[ii][0]);
      }
    }
  } // ... evaluate< ..., 1, 1 >(...)

  template <class E, class D, int d, class R>
  void evaluate(const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_factor,
                const Stuff::LocalfunctionInterface<E, D, d, R, 2, 2>& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& testBase,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& ansatzBase,
                const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret) const
  {
    evaluate_matrix_valued_(local_diffusion_factor, local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

  template <class E, class D, int d, class R>
  void evaluate(const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_factor,
                const Stuff::LocalfunctionInterface<E, D, d, R, 3, 3>& local_diffusion_tensor,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& testBase,
                const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& ansatzBase,
                const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret) const
  {
    evaluate_matrix_valued_(local_diffusion_factor, local_diffusion_tensor, testBase, ansatzBase, localPoint, ret);
  }

private:
  template <class E, class D, int d, class R>
  void evaluate_matrix_valued_(const Stuff::LocalfunctionInterface<E, D, d, R, 1, 1>& local_diffusion_factor,
                               const Stuff::LocalfunctionInterface<E, D, d, R, d, d>& local_diffusion_tensor,
                               const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& testBase,
                               const Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>& ansatzBase,
                               const Dune::FieldVector<D, d>& localPoint, Dune::DynamicMatrix<R>& ret) const
  {
    typedef typename Stuff::LocalfunctionSetInterface<E, D, d, R, 1, 1>::JacobianRangeType JacobianRangeType;
    // evaluate local functions
    const auto local_diffusion_factor_value = local_diffusion_factor.evaluate(localPoint);
    auto local_diffusion_tensor_value       = local_diffusion_tensor.evaluate(localPoint);
    local_diffusion_tensor_value *= local_diffusion_factor_value[0];
    // evaluate test gradient
    const size_t rows = testBase.size();
    std::vector<JacobianRangeType> testGradients(rows, JacobianRangeType(0));
    testBase.jacobian(localPoint, testGradients);
    // evaluate ansatz gradient
    const size_t cols = ansatzBase.size();
    std::vector<JacobianRangeType> ansatzGradients(cols, JacobianRangeType(0));
    ansatzBase.jacobian(localPoint, ansatzGradients);
    // compute products
    assert(ret.rows() >= rows);
    assert(ret.cols() >= cols);
    FieldVector<D, d> product(0.0);
    for (size_t ii = 0; ii < rows; ++ii) {
      auto& retRow = ret[ii];
      for (size_t jj = 0; jj < cols; ++jj) {
        local_diffusion_tensor_value.mv(ansatzGradients[jj][0], product);
        retRow[jj] = product * testGradients[ii][0];
      }
    }
  } // ... evaluate_matrix_valued_(...)

  const DiffusionFactorType& diffusion_factor_;
  const DiffusionTensorType& diffusion_tensor_;
}; // class LocalElliptic

} // namespace Evaluation
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_PLAYGROUND_EVALUATION_ELLIPTIC_HH
<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#define _POSIX_SOURCE

#include "condor_common.h"
#include "condor_constants.h"
#include "condor_io.h"
#include "condor_debug.h"
#include "internet.h"

#if !defined(GSS_AUTHENTICATION)
#define AuthSock ReliSock
#else

//include rest of file in this #ELSE
#include "globus_gss_assist.h"
#include "auth_sock.h"

/*******************************************************************/
gss_cred_id_t AuthSock::credential_handle = GSS_C_NO_CREDENTIAL;

/*******************************************************************/

int
AuthSock::lookup_user( char *client_name ) {
	/* return -1 for error */
	char filename[MAXPATHLEN];
	char command[MAXPATHLEN+32];

	sprintf( filename, "%s/index.txt", getenv( "X509_CERT_DIR" ) );
//fix this to do a better job, this is just a quick hack!
	sprintf( command, "grep -q 'V.*%s' %s", client_name, filename );

	if ( system( command ) ) {
		dprintf( D_ALWAYS, "unable to find V entry for %s in %s\n",
				client_name, filename );
		return -1;
	}
	dprintf( D_ALWAYS,"GSS authenticated %s\n", client_name );
	return 0;
}

/*******************************************************************/
//cannot make this an AuthSock method, since gss_assist method expects
//three parms, methods have hidden "this" parm first. Couldn't figure out
//a way around this, so made AuthSock have a member of type AuthComms
//to pass in to this method to manage buffer space.  //mju
int
authsock_get(void *arg, void **bufp, size_t *sizep)
{
	/* globus code which calls this function expects 0/-1 return vals */

	//authsock must "hold onto" GSS state, pass in struct with comms stuff
	AuthComms *comms = (AuthComms *) arg;
	AuthSock *sock = comms->sock;
	size_t stat;

	sock->decode();

	//read size of data to read
	stat = sock->code( *((int *)sizep) );

	*bufp = malloc( *((int *)sizep) );
	if ( !*bufp ) {
		dprintf( D_ALWAYS, "malloc failure authsock_get\n" );
		stat = FALSE;
	}

	//if successfully read size and malloced, read data
	if ( stat )
		sock->code_bytes( *bufp, *((int *)sizep) );

	sock->end_of_message();

	//check to ensure comms were successful
	if ( !stat ) {
		dprintf( D_ALWAYS, "authsock_get (read from socket) failure\n" );
		return -1;
	}
	return 0;
}

/*******************************************************************/
int
authsock_put(void *arg,  void *buf, size_t size)
{
	//param is just a AS*
	AuthSock *sock = (AuthSock *) arg;
	int stat;

	sock->encode();

	//send size of data to send
	stat = sock->code( (int &)size );
	//if successful, send the data
	if ( stat ) {
		if ( !(stat = sock->code_bytes( buf, ((int) size )) ) ) {
			dprintf( D_ALWAYS, "failure sending data (%d bytes) over sock\n",size);
		}
	}
	else {
		dprintf( D_ALWAYS, "failure sending size (%d) over sock\n", size );
	}

	sock->end_of_message();

	//ensure data send was successful
	if ( !stat ) {
		dprintf( D_ALWAYS, "authsock_put (write to socket) failure\n" );
		return -1;
	}
	return 0;
}

/*******************************************************************/
int
AuthSock::authenticate_user()
{
	OM_uint32 major_status;
	OM_uint32 minor_status;

	if ( credential_handle != GSS_C_NO_CREDENTIAL ) { // user already auth'd
		dprintf( D_FULLDEBUG, "This process has a valid certificate & key\n" );
		return TRUE;
	}

	// ensure all env vars are in place, acquire cred will fail otherwise
	if ( !( getenv( "X509_USER_CERT" ) && getenv( "X509_USER_KEY" )
			&& getenv( "X509_CERT_DIR" ) ) )
	{
		//don't log error, since this can be called before env vars are set!
		dprintf(D_FULLDEBUG,"X509 env vars not set yet (might not be error)\n");
		return FALSE;
	}

	//use gss-assist to verify user (not connection)
	//this method will prompt for password if private key is encrypted!
	major_status = globus_gss_assist_acquire_cred(&minor_status,
		GSS_C_BOTH, &credential_handle);

	if (major_status != GSS_S_COMPLETE)
	{
		dprintf( D_ALWAYS, "gss-api failure initializing user credentials, "
				"stats: 0x%x\n", major_status );
		return FALSE;
	}

	dprintf( D_FULLDEBUG, "This process has a valid certificate & key\n" );
	return TRUE;
}

/*******************************************************************/
int
AuthSock::auth_connection_client()
{
	OM_uint32						  major_status = 0;
	OM_uint32						  minor_status = 0;
	int								  token_status = 0;
	OM_uint32						  ret_flags = 0;
	gss_ctx_id_t					  context_handle = GSS_C_NO_CONTEXT;

	if ( !authenticate_user() ) {
		dprintf( D_ALWAYS,
			"failure authenticating client from auth_connection_client\n" );
		return FALSE;
	}

	gateKeeper = getenv( "CONDOR_GATEKEEPER" );

	if ( !gateKeeper ) {
		dprintf( D_ALWAYS, "env var CONDOR_GATEKEEPER not set" );
		return FALSE;
	}

	authComms.sock = this;
	authComms.buffer = NULL;
	authComms.size = 0;

	major_status = globus_gss_assist_init_sec_context(&minor_status,
		  credential_handle, &context_handle,
		  gateKeeper,
		  GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG,
		  &ret_flags, &token_status,
		  authsock_get, (void *) &authComms,
		  authsock_put, (void *) this
	);

	if (major_status != GSS_S_COMPLETE)
	{
		dprintf( D_ALWAYS, "failed auth connection client, gss status: 0x%x\n",
								major_status );
		return FALSE;
	}

//	decode();
//	code( GSSClientname );
//	end_of_message();

	/*
	 * once connection is authenticated, don't need sec_context any more
	 * ???might need sec_context for PROXIES???
	 */
	gss_delete_sec_context( &minor_status, &context_handle, GSS_C_NO_BUFFER );

	conn_auth_state = auth_cert;

	dprintf(D_FULLDEBUG,"valid GSS connection established to %s\n", gateKeeper);
	return TRUE;
}

/*******************************************************************/
int
AuthSock::auth_connection_server( AuthSock &authsock)
{
	int rc;
	OM_uint32 major_status = 0;
	OM_uint32 minor_status = 0;
	int		 token_status = 0;
	OM_uint32 ret_flags = 0;
	gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;

	if ( !authenticate_user() ) {
		dprintf( D_ALWAYS,
			"failure authenticating self in auth_connection_server\n" );
		return FALSE;
	}
	if ( authsock.GSSClientname )
		free ( GSSClientname );
	authsock.GSSClientname = NULL;

	authComms.sock = &authsock;
	authComms.buffer = NULL;
	authComms.size = 0;

	major_status = globus_gss_assist_accept_sec_context(&minor_status,
				 &context_handle, credential_handle,
				 &authsock.GSSClientname,
				 &ret_flags, NULL, /* don't need user_to_user */
				 &token_status,
				 authsock_get, (void *) &authComms,
				 authsock_put, (void *) &authsock
	);

	if ( (major_status != GSS_S_COMPLETE) ||
			( ( lookup_user( authsock.GSSClientname ) ) < 0 ) )
	{
		if (major_status != GSS_S_COMPLETE) {
			dprintf(D_ALWAYS, "server: GSS failure authenticating %s 0x%x\n",
					"client, status: ", major_status );
		}
		else
			dprintf( D_ALWAYS, "server: user lookup failure.\n" );
		if ( authsock.GSSClientname ) {
			free( authsock.GSSClientname );
			authsock.GSSClientname = NULL;
		}
		return FALSE;
	}

//	authsock.encode();
//	authsock.code( authsock.GSSClientname );
//	authsock.end_of_message();

	/*
	 * once connection is authenticated, don't need sec_context any more
	 * ???might need sec_context for PROXIES???
	 */
	gss_delete_sec_context( &minor_status, &context_handle, GSS_C_NO_BUFFER );

	authsock.Set_conn_auth_state( auth_cert );

	dprintf(D_FULLDEBUG,"valid GSS connection established to %s\n",
			authsock.GSSClientname);
	return TRUE;
}

/*******************************************************************/
AuthSock::AuthSock():ReliSock() {
	conn_type = auth_none;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::AuthSock(					/* listen on port		*/
	int		port
	)
	: ReliSock(port)
{
	conn_type = auth_server;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::AuthSock(					/* listen on serv		*/
	char	*serv
	)
	: ReliSock(serv)
{
	conn_type = auth_server;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::AuthSock(
	char	*host,
	int		port,
	int		timeout_val
	)
	: ReliSock(host,port,timeout_val) /* does connect */
{
	conn_type = auth_client;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::AuthSock(
	char	*host,
	char	*serv,
	int		timeout_val
	)
	: ReliSock(host,serv,timeout_val) /* does connect */
{
	conn_type = auth_client;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::~AuthSock()
{
	if ( GSSClientname ) free ( GSSClientname );
	close();
}

/*******************************************************************/
int
AuthSock::accept(
	AuthSock &sock
	)
{
	sock.Set_conn_type( auth_server );
	return ReliSock::accept( (ReliSock&) sock );
}

/*******************************************************************/
AuthSock *AuthSock::accept()
{
	AuthSock *c_rs;
	int c_sock;

	conn_type = auth_server;

	if (!(c_rs = new AuthSock())) return (AuthSock *)0;

	if ((c_sock = accept(*c_rs)) < 0) {
		delete c_rs;
		return (AuthSock *)0;
	}

	return c_rs;
}

/*******************************************************************/
int AuthSock::connect(
	char	*host,
	int		port
	)
{
	conn_type = auth_client;
	return ReliSock::connect(host, port);
}

/*******************************************************************/
int AuthSock::authenticate() {
	//don't just return TRUE if isAuthenticated() == TRUE, since
	//we should BALANCE calls of authenticate() on client/server side
	//just like end_of_message() calls must balance!

	if ( !authenticate_user() ) {
		dprintf( D_ALWAYS, "authenticate: user creds not established\n" );
		return FALSE;
	}

	switch ( conn_type ) {
		case auth_server :
			dprintf(D_FULLDEBUG,"about to authenticate client from server\n" );
			return ( auth_connection_server( *this ) );
		case auth_client :
			dprintf(D_FULLDEBUG,"about to authenticate server from client\n" );
			return ( auth_connection_client() );
		default :
			dprintf( D_ALWAYS,"authenticate:needed to have connected/accepted\n" );
			return FALSE;
	}
}

/*******************************************************************/
void AuthSock::auth_setup() {
	authComms.buffer = NULL;
	authComms.size = 0;
	GSSClientname = NULL;
}

#endif //#!defined GSS_AUTHENTICATION
<commit_msg>added real check of user database rather than just grepping the file for a 'V' valid entry and the users name. Also a bit of cosmetic changes.<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#define _POSIX_SOURCE

#include "condor_common.h"
#include "condor_constants.h"
#include "condor_io.h"
#include "condor_debug.h"
#include "internet.h"

#if !defined(GSS_AUTHENTICATION)
#define AuthSock ReliSock
#else

//include rest of file in this #ELSE
#include "globus_gss_assist.h"
#include "auth_sock.h"

/*******************************************************************/
gss_cred_id_t AuthSock::credential_handle = GSS_C_NO_CREDENTIAL;

/*******************************************************************/

int
AuthSock::lookup_user( char *client_name ) {
	/* return -1 for error */
	char filename[MAXPATHLEN];
	char command[MAXPATHLEN+32];

	sprintf( filename, "%s/index.txt", getenv( "X509_CERT_DIR" ) );

	FILE *index;
	if ( !(index = fopen(  filename, "r" ) ) ) {
		dprintf( D_ALWAYS, "unable to open index file %s, errno %d\n",
				filename, errno );
		return -1;
	}

	//find entry
	int found = 0;
	char line[81];
	while ( !found && fgets( line, 80, index ) ) {
		//Valid user entries have 'V' as first byte in their cert db entry
		if ( line[0] == 'V' &&  strstr( line, client_name ) ) {
			found = 1;
		}
	}
	fclose( index );
	if ( !found ) {
		dprintf( D_ALWAYS, "unable to find V entry for %s in %s\n",
				filename, client_name );
		return( -1 );
	}

	dprintf( D_ALWAYS,"GSS authenticated %s\n", client_name );
	return 0;
}

/*******************************************************************/
//cannot make this an AuthSock method, since gss_assist method expects
//three parms, methods have hidden "this" parm first. Couldn't figure out
//a way around this, so made AuthSock have a member of type AuthComms
//to pass in to this method to manage buffer space.  //mju
int
authsock_get(void *arg, void **bufp, size_t *sizep)
{
	/* globus code which calls this function expects 0/-1 return vals */

	//authsock must "hold onto" GSS state, pass in struct with comms stuff
	AuthComms *comms = (AuthComms *) arg;
	AuthSock *sock = comms->sock;
	size_t stat;

	sock->decode();

	//read size of data to read
	stat = sock->code( *((int *)sizep) );

	*bufp = malloc( *((int *)sizep) );
	if ( !*bufp ) {
		dprintf( D_ALWAYS, "malloc failure authsock_get\n" );
		stat = FALSE;
	}

	//if successfully read size and malloced, read data
	if ( stat )
		sock->code_bytes( *bufp, *((int *)sizep) );

	sock->end_of_message();

	//check to ensure comms were successful
	if ( !stat ) {
		dprintf( D_ALWAYS, "authsock_get (read from socket) failure\n" );
		return -1;
	}
	return 0;
}

/*******************************************************************/
int
authsock_put(void *arg,  void *buf, size_t size)
{
	//param is just a AS*
	AuthSock *sock = (AuthSock *) arg;
	int stat;

	sock->encode();

	//send size of data to send
	stat = sock->code( (int &)size );
	//if successful, send the data
	if ( stat ) {
		if ( !(stat = sock->code_bytes( buf, ((int) size )) ) ) {
			dprintf( D_ALWAYS, "failure sending data (%d bytes) over sock\n",size);
		}
	}
	else {
		dprintf( D_ALWAYS, "failure sending size (%d) over sock\n", size );
	}

	sock->end_of_message();

	//ensure data send was successful
	if ( !stat ) {
		dprintf( D_ALWAYS, "authsock_put (write to socket) failure\n" );
		return -1;
	}
	return 0;
}

/*******************************************************************/
int
AuthSock::authenticate_user()
{
	OM_uint32 major_status;
	OM_uint32 minor_status;

	if ( credential_handle != GSS_C_NO_CREDENTIAL ) { // user already auth'd
		dprintf( D_FULLDEBUG, "This process has a valid certificate & key\n" );
		return TRUE;
	}

	// ensure all env vars are in place, acquire cred will fail otherwise
	if ( !( getenv( "X509_USER_CERT" ) && getenv( "X509_USER_KEY" )
			&& getenv( "X509_CERT_DIR" ) ) )
	{
		//don't log error, since this can be called before env vars are set!
		dprintf(D_FULLDEBUG,"X509 env vars not set yet (might not be error)\n");
		return FALSE;
	}

	//use gss-assist to verify user (not connection)
	//this method will prompt for password if private key is encrypted!
	major_status = globus_gss_assist_acquire_cred(&minor_status,
		GSS_C_BOTH, &credential_handle);

	if (major_status != GSS_S_COMPLETE)
	{
		dprintf( D_ALWAYS, "gss-api failure initializing user credentials, "
				"stats: 0x%x\n", major_status );
		credential_handle = GSS_C_NO_CREDENTIAL;
		return FALSE;
	}

	dprintf( D_FULLDEBUG, "This process has a valid certificate & key\n" );
	return TRUE;
}

/*******************************************************************/
int
AuthSock::auth_connection_client()
{
	OM_uint32						  major_status = 0;
	OM_uint32						  minor_status = 0;
	int								  token_status = 0;
	OM_uint32						  ret_flags = 0;
	gss_ctx_id_t					  context_handle = GSS_C_NO_CONTEXT;

	if ( !authenticate_user() ) {
		dprintf( D_ALWAYS,
			"failure authenticating client from auth_connection_client\n" );
		return FALSE;
	}

	gateKeeper = getenv( "CONDOR_GATEKEEPER" );

	if ( !gateKeeper ) {
		dprintf( D_ALWAYS, "env var CONDOR_GATEKEEPER not set" );
		return FALSE;
	}

	authComms.sock = this;
	authComms.buffer = NULL;
	authComms.size = 0;

	major_status = globus_gss_assist_init_sec_context(&minor_status,
		  credential_handle, &context_handle,
		  gateKeeper,
		  GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG,
		  &ret_flags, &token_status,
		  authsock_get, (void *) &authComms,
		  authsock_put, (void *) this
	);

	if (major_status != GSS_S_COMPLETE)
	{
		dprintf( D_ALWAYS, "failed auth connection client, gss status: 0x%x\n",
								major_status );
		return FALSE;
	}

	/*
	 * once connection is authenticated, don't need sec_context any more
	 * ???might need sec_context for PROXIES???
	 */
	gss_delete_sec_context( &minor_status, &context_handle, GSS_C_NO_BUFFER );

	conn_auth_state = auth_cert;

	dprintf(D_FULLDEBUG,"valid GSS connection established to %s\n", gateKeeper);
	return TRUE;
}

/*******************************************************************/
int
AuthSock::auth_connection_server( AuthSock &authsock)
{
	int rc;
	OM_uint32 major_status = 0;
	OM_uint32 minor_status = 0;
	int		 token_status = 0;
	OM_uint32 ret_flags = 0;
	gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;

	if ( !authenticate_user() ) {
		dprintf( D_ALWAYS,
			"failure authenticating self in auth_connection_server\n" );
		return FALSE;
	}
	if ( authsock.GSSClientname )
		free ( GSSClientname );
	authsock.GSSClientname = NULL;

	authComms.sock = &authsock;
	authComms.buffer = NULL;
	authComms.size = 0;

	major_status = globus_gss_assist_accept_sec_context(&minor_status,
				 &context_handle, credential_handle,
				 &authsock.GSSClientname,
				 &ret_flags, NULL, /* don't need user_to_user */
				 &token_status,
				 authsock_get, (void *) &authComms,
				 authsock_put, (void *) &authsock
	);

	if ( (major_status != GSS_S_COMPLETE) ||
			( ( lookup_user( authsock.GSSClientname ) ) < 0 ) )
	{
		if (major_status != GSS_S_COMPLETE) {
			dprintf(D_ALWAYS, "server: GSS failure authenticating %s 0x%x\n",
					"client, status: ", major_status );
		}
		else
			dprintf( D_ALWAYS, "server: user lookup failure.\n" );
		if ( authsock.GSSClientname ) {
			free( authsock.GSSClientname );
			authsock.GSSClientname = NULL;
		}
		return FALSE;
	}

	/*
	 * once connection is authenticated, don't need sec_context any more
	 * ???might need sec_context for PROXIES???
	 */
	gss_delete_sec_context( &minor_status, &context_handle, GSS_C_NO_BUFFER );

	authsock.Set_conn_auth_state( auth_cert );

	dprintf(D_FULLDEBUG,"valid GSS connection established to %s\n",
			authsock.GSSClientname);
	return TRUE;
}

/*******************************************************************/
AuthSock::AuthSock():ReliSock() {
	conn_type = auth_none;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::AuthSock(					/* listen on port		*/
	int		port
	)
	: ReliSock(port)
{
	conn_type = auth_server;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::AuthSock(					/* listen on serv		*/
	char	*serv
	)
	: ReliSock(serv)
{
	conn_type = auth_server;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::AuthSock(
	char	*host,
	int		port,
	int		timeout_val
	)
	: ReliSock(host,port,timeout_val) /* does connect */
{
	conn_type = auth_client;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::AuthSock(
	char	*host,
	char	*serv,
	int		timeout_val
	)
	: ReliSock(host,serv,timeout_val) /* does connect */
{
	conn_type = auth_client;
	auth_setup();
//	authenticate_user();
}

/*******************************************************************/
AuthSock::~AuthSock()
{
	if ( GSSClientname ) free ( GSSClientname );
	close();
}

/*******************************************************************/
int
AuthSock::accept(
	AuthSock &sock
	)
{
	sock.Set_conn_type( auth_server );
	return ReliSock::accept( (ReliSock&) sock );
}

/*******************************************************************/
AuthSock *AuthSock::accept()
{
	AuthSock *c_rs;
	int c_sock;

	conn_type = auth_server;

	if (!(c_rs = new AuthSock())) return (AuthSock *)0;

	if ((c_sock = accept(*c_rs)) < 0) {
		delete c_rs;
		return (AuthSock *)0;
	}

	return c_rs;
}

/*******************************************************************/
int AuthSock::connect(
	char	*host,
	int		port
	)
{
	conn_type = auth_client;
	return ReliSock::connect(host, port);
}

/*******************************************************************/
int AuthSock::authenticate() {
	//don't just return TRUE if isAuthenticated() == TRUE, since
	//we should BALANCE calls of authenticate() on client/server side
	//just like end_of_message() calls must balance!

	if ( !authenticate_user() ) {
		dprintf( D_ALWAYS, "authenticate: user creds not established\n" );
		return FALSE;
	}

	switch ( conn_type ) {
		case auth_server :
			dprintf(D_FULLDEBUG,"about to authenticate client from server\n" );
			return ( auth_connection_server( *this ) );
		case auth_client :
			dprintf(D_FULLDEBUG,"about to authenticate server from client\n" );
			return ( auth_connection_client() );
		default :
			dprintf( D_ALWAYS,"authenticate:needed to have connected/accepted\n" );
			return FALSE;
	}
}

/*******************************************************************/
void AuthSock::auth_setup() {
	authComms.buffer = NULL;
	authComms.size = 0;
	GSSClientname = NULL;
}

#endif //#!defined GSS_AUTHENTICATION
<|endoftext|>