<commit_before>/*
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright (C) 2015 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "cql3/statements/cf_prop_defs.hh"

namespace cql3 {

namespace statements {

const sstring cf_prop_defs::KW_COMMENT = "comment";
const sstring cf_prop_defs::KW_READREPAIRCHANCE = "read_repair_chance";
const sstring cf_prop_defs::KW_DCLOCALREADREPAIRCHANCE = "dclocal_read_repair_chance";
const sstring cf_prop_defs::KW_GCGRACESECONDS = "gc_grace_seconds";
const sstring cf_prop_defs::KW_MINCOMPACTIONTHRESHOLD = "min_threshold";
const sstring cf_prop_defs::KW_MAXCOMPACTIONTHRESHOLD = "max_threshold";
const sstring cf_prop_defs::KW_CACHING = "caching";
const sstring cf_prop_defs::KW_DEFAULT_TIME_TO_LIVE = "default_time_to_live";
const sstring cf_prop_defs::KW_MIN_INDEX_INTERVAL = "min_index_interval";
const sstring cf_prop_defs::KW_MAX_INDEX_INTERVAL = "max_index_interval";
const sstring cf_prop_defs::KW_SPECULATIVE_RETRY = "speculative_retry";
const sstring cf_prop_defs::KW_BF_FP_CHANCE = "bloom_filter_fp_chance";
const sstring cf_prop_defs::KW_MEMTABLE_FLUSH_PERIOD = "memtable_flush_period_in_ms";

const sstring cf_prop_defs::KW_COMPACTION = "compaction";
const sstring cf_prop_defs::KW_COMPRESSION = "compression";

const sstring cf_prop_defs::COMPACTION_STRATEGY_CLASS_KEY = "class";

void cf_prop_defs::validate() {
    // Skip validation if the comapction strategy class is already set as it means we've alreayd
    // prepared (and redoing it would set strategyClass back to null, which we don't want)
    if (_compaction_strategy_class) {
        return;
    }

    static std::set<sstring> keywords({
        KW_COMMENT, KW_READREPAIRCHANCE, KW_DCLOCALREADREPAIRCHANCE,
        KW_GCGRACESECONDS, KW_CACHING, KW_DEFAULT_TIME_TO_LIVE,
        KW_MIN_INDEX_INTERVAL, KW_MAX_INDEX_INTERVAL, KW_SPECULATIVE_RETRY,
        KW_BF_FP_CHANCE, KW_MEMTABLE_FLUSH_PERIOD, KW_COMPACTION,
        KW_COMPRESSION,
    });
    static std::set<sstring> obsolete_keywords({
        sstring("index_interval"),
        sstring("replicate_on_write"),
        sstring("populate_io_cache_on_flush"),
    });
    property_definitions::validate(keywords, obsolete_keywords);

    auto compaction_options = get_compaction_options();
    if (!compaction_options.empty()) {
        auto strategy = compaction_options.find(COMPACTION_STRATEGY_CLASS_KEY);
        if (strategy == compaction_options.end()) {
            throw exceptions::configuration_exception(sstring("Missing sub-option '") + COMPACTION_STRATEGY_CLASS_KEY + "' for the '" + KW_COMPACTION + "' option.");
        }
        _compaction_strategy_class = sstables::compaction_strategy::type(strategy->second);
#if 0
       compactionOptions.remove(COMPACTION_STRATEGY_CLASS_KEY);

       CFMetaData.validateCompactionOptions(compactionStrategyClass, compactionOptions);
#endif
    }

    auto compression_options = get_compression_options();
    if (!compression_options.empty()) {
        auto sstable_compression_class = compression_options.find(sstring(compression_parameters::SSTABLE_COMPRESSION));
        if (sstable_compression_class == compression_options.end()) {
            throw exceptions::configuration_exception(sstring("Missing sub-option '") + compression_parameters::SSTABLE_COMPRESSION + "' for the '" + KW_COMPRESSION + "' option.");
        }
        compression_parameters cp(compression_options);
        cp.validate();
    }

    validate_minimum_int(KW_DEFAULT_TIME_TO_LIVE, 0, DEFAULT_DEFAULT_TIME_TO_LIVE);

    auto min_index_interval = get_int(KW_MIN_INDEX_INTERVAL, DEFAULT_MIN_INDEX_INTERVAL);
    auto max_index_interval = get_int(KW_MAX_INDEX_INTERVAL, DEFAULT_MAX_INDEX_INTERVAL);
    if (min_index_interval < 1) {
        throw exceptions::configuration_exception(KW_MIN_INDEX_INTERVAL + " must be greater than 0");
    }
    if (max_index_interval < min_index_interval) {
        throw exceptions::configuration_exception(KW_MAX_INDEX_INTERVAL + " must be greater than " + KW_MIN_INDEX_INTERVAL);
    }

    speculative_retry::from_sstring(get_string(KW_SPECULATIVE_RETRY, speculative_retry(speculative_retry::type::NONE, 0).to_sstring()));
}

std::map<sstring, sstring> cf_prop_defs::get_compaction_options() const {
    auto compaction_options = get_map(KW_COMPACTION);
    if (compaction_options ) {
        return compaction_options.value();
    }
    return std::map<sstring, sstring>{};
}

std::map<sstring, sstring> cf_prop_defs::get_compression_options() const {
    auto compression_options = get_map(KW_COMPRESSION);
    if (compression_options) {
        return compression_options.value();
    }
    return std::map<sstring, sstring>{};
}

int32_t cf_prop_defs::get_default_time_to_live() const
{
    return get_int(KW_DEFAULT_TIME_TO_LIVE, 0);
}

void cf_prop_defs::apply_to_builder(schema_builder& builder) {
    if (has_property(KW_COMMENT)) {
        builder.set_comment(get_string(KW_COMMENT, ""));
    }

    if (has_property(KW_READREPAIRCHANCE)) {
        builder.set_read_repair_chance(get_double(KW_READREPAIRCHANCE, builder.get_read_repair_chance()));
    }

    if (has_property(KW_DCLOCALREADREPAIRCHANCE)) {
        builder.set_dc_local_read_repair_chance(get_double(KW_DCLOCALREADREPAIRCHANCE, builder.get_dc_local_read_repair_chance()));
    }

    if (has_property(KW_GCGRACESECONDS)) {
        builder.set_gc_grace_seconds(get_int(KW_GCGRACESECONDS, builder.get_gc_grace_seconds()));
    }

    std::experimental::optional<sstring> tmp_value = {};
    if (has_property(KW_MINCOMPACTIONTHRESHOLD)) {
        if (get_compaction_options().count(KW_MINCOMPACTIONTHRESHOLD)) {
            tmp_value = get_compaction_options().at(KW_MINCOMPACTIONTHRESHOLD);
        }
    }
    int min_compaction_threshold = to_int(KW_MINCOMPACTIONTHRESHOLD, tmp_value, builder.get_min_compaction_threshold());

    tmp_value = {};
    if (has_property(KW_MAXCOMPACTIONTHRESHOLD)) {
        if (get_compaction_options().count(KW_MAXCOMPACTIONTHRESHOLD)) {
            tmp_value = get_compaction_options().at(KW_MAXCOMPACTIONTHRESHOLD);
        }
    }
    int max_compaction_threshold = to_int(KW_MAXCOMPACTIONTHRESHOLD, tmp_value, builder.get_max_compaction_threshold());

    if (min_compaction_threshold <= 0 || max_compaction_threshold <= 0)
        throw exceptions::configuration_exception("Disabling compaction by setting compaction thresholds to 0 has been deprecated, set the compaction option 'enabled' to false instead.");
    builder.set_min_compaction_threshold(min_compaction_threshold);
    builder.set_max_compaction_threshold(max_compaction_threshold);

    builder.set_default_time_to_live(gc_clock::duration(get_int(KW_DEFAULT_TIME_TO_LIVE, DEFAULT_DEFAULT_TIME_TO_LIVE)));

    if (has_property(KW_SPECULATIVE_RETRY)) {
        builder.set_speculative_retry(get_string(KW_SPECULATIVE_RETRY, builder.get_speculative_retry().to_sstring()));
    }

    if (has_property(KW_MEMTABLE_FLUSH_PERIOD)) {
        builder.set_memtable_flush_period(get_int(KW_MEMTABLE_FLUSH_PERIOD, builder.get_memtable_flush_period()));
    }

    if (has_property(KW_MIN_INDEX_INTERVAL)) {
        builder.set_min_index_interval(get_int(KW_MIN_INDEX_INTERVAL, builder.get_min_index_interval()));
    }

    if (has_property(KW_MAX_INDEX_INTERVAL)) {
        builder.set_max_index_interval(get_int(KW_MAX_INDEX_INTERVAL, builder.get_max_index_interval()));
    }

    if (_compaction_strategy_class) {
        builder.set_compaction_strategy(*_compaction_strategy_class);
        builder.set_compaction_strategy_options(get_compaction_options());
    }

    builder.set_bloom_filter_fp_chance(get_double(KW_BF_FP_CHANCE, builder.get_bloom_filter_fp_chance()));
    if (!get_compression_options().empty()) {
        builder.set_compressor_params(compression_parameters(get_compression_options()));
    }
#if 0
    CachingOptions cachingOptions = getCachingOptions();
    if (cachingOptions != null)
        cfm.caching(cachingOptions);
#endif
}

void cf_prop_defs::validate_minimum_int(const sstring& field, int32_t minimum_value, int32_t default_value) const
{
    auto val = get_int(field, default_value);
    if (val < minimum_value) {
        throw exceptions::configuration_exception(sprint("%s cannot be smaller than %s, (default %s)",
                                                         field, minimum_value, default_value));
    }
}

}

}
<commit_msg>cql3::statements::cf_prop_defs: Fix compation min/max not handled<commit_after>/*
 * 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright (C) 2015 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla 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 Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "cql3/statements/cf_prop_defs.hh"

namespace cql3 {

namespace statements {

const sstring cf_prop_defs::KW_COMMENT = "comment";
const sstring cf_prop_defs::KW_READREPAIRCHANCE = "read_repair_chance";
const sstring cf_prop_defs::KW_DCLOCALREADREPAIRCHANCE = "dclocal_read_repair_chance";
const sstring cf_prop_defs::KW_GCGRACESECONDS = "gc_grace_seconds";
const sstring cf_prop_defs::KW_MINCOMPACTIONTHRESHOLD = "min_threshold";
const sstring cf_prop_defs::KW_MAXCOMPACTIONTHRESHOLD = "max_threshold";
const sstring cf_prop_defs::KW_CACHING = "caching";
const sstring cf_prop_defs::KW_DEFAULT_TIME_TO_LIVE = "default_time_to_live";
const sstring cf_prop_defs::KW_MIN_INDEX_INTERVAL = "min_index_interval";
const sstring cf_prop_defs::KW_MAX_INDEX_INTERVAL = "max_index_interval";
const sstring cf_prop_defs::KW_SPECULATIVE_RETRY = "speculative_retry";
const sstring cf_prop_defs::KW_BF_FP_CHANCE = "bloom_filter_fp_chance";
const sstring cf_prop_defs::KW_MEMTABLE_FLUSH_PERIOD = "memtable_flush_period_in_ms";

const sstring cf_prop_defs::KW_COMPACTION = "compaction";
const sstring cf_prop_defs::KW_COMPRESSION = "compression";

const sstring cf_prop_defs::COMPACTION_STRATEGY_CLASS_KEY = "class";

void cf_prop_defs::validate() {
    // Skip validation if the comapction strategy class is already set as it means we've alreayd
    // prepared (and redoing it would set strategyClass back to null, which we don't want)
    if (_compaction_strategy_class) {
        return;
    }

    static std::set<sstring> keywords({
        KW_COMMENT, KW_READREPAIRCHANCE, KW_DCLOCALREADREPAIRCHANCE,
        KW_GCGRACESECONDS, KW_CACHING, KW_DEFAULT_TIME_TO_LIVE,
        KW_MIN_INDEX_INTERVAL, KW_MAX_INDEX_INTERVAL, KW_SPECULATIVE_RETRY,
        KW_BF_FP_CHANCE, KW_MEMTABLE_FLUSH_PERIOD, KW_COMPACTION,
        KW_COMPRESSION,
    });
    static std::set<sstring> obsolete_keywords({
        sstring("index_interval"),
        sstring("replicate_on_write"),
        sstring("populate_io_cache_on_flush"),
    });
    property_definitions::validate(keywords, obsolete_keywords);

    auto compaction_options = get_compaction_options();
    if (!compaction_options.empty()) {
        auto strategy = compaction_options.find(COMPACTION_STRATEGY_CLASS_KEY);
        if (strategy == compaction_options.end()) {
            throw exceptions::configuration_exception(sstring("Missing sub-option '") + COMPACTION_STRATEGY_CLASS_KEY + "' for the '" + KW_COMPACTION + "' option.");
        }
        _compaction_strategy_class = sstables::compaction_strategy::type(strategy->second);
#if 0
       compactionOptions.remove(COMPACTION_STRATEGY_CLASS_KEY);

       CFMetaData.validateCompactionOptions(compactionStrategyClass, compactionOptions);
#endif
    }

    auto compression_options = get_compression_options();
    if (!compression_options.empty()) {
        auto sstable_compression_class = compression_options.find(sstring(compression_parameters::SSTABLE_COMPRESSION));
        if (sstable_compression_class == compression_options.end()) {
            throw exceptions::configuration_exception(sstring("Missing sub-option '") + compression_parameters::SSTABLE_COMPRESSION + "' for the '" + KW_COMPRESSION + "' option.");
        }
        compression_parameters cp(compression_options);
        cp.validate();
    }

    validate_minimum_int(KW_DEFAULT_TIME_TO_LIVE, 0, DEFAULT_DEFAULT_TIME_TO_LIVE);

    auto min_index_interval = get_int(KW_MIN_INDEX_INTERVAL, DEFAULT_MIN_INDEX_INTERVAL);
    auto max_index_interval = get_int(KW_MAX_INDEX_INTERVAL, DEFAULT_MAX_INDEX_INTERVAL);
    if (min_index_interval < 1) {
        throw exceptions::configuration_exception(KW_MIN_INDEX_INTERVAL + " must be greater than 0");
    }
    if (max_index_interval < min_index_interval) {
        throw exceptions::configuration_exception(KW_MAX_INDEX_INTERVAL + " must be greater than " + KW_MIN_INDEX_INTERVAL);
    }

    speculative_retry::from_sstring(get_string(KW_SPECULATIVE_RETRY, speculative_retry(speculative_retry::type::NONE, 0).to_sstring()));
}

std::map<sstring, sstring> cf_prop_defs::get_compaction_options() const {
    auto compaction_options = get_map(KW_COMPACTION);
    if (compaction_options ) {
        return compaction_options.value();
    }
    return std::map<sstring, sstring>{};
}

std::map<sstring, sstring> cf_prop_defs::get_compression_options() const {
    auto compression_options = get_map(KW_COMPRESSION);
    if (compression_options) {
        return compression_options.value();
    }
    return std::map<sstring, sstring>{};
}

int32_t cf_prop_defs::get_default_time_to_live() const
{
    return get_int(KW_DEFAULT_TIME_TO_LIVE, 0);
}

void cf_prop_defs::apply_to_builder(schema_builder& builder) {
    if (has_property(KW_COMMENT)) {
        builder.set_comment(get_string(KW_COMMENT, ""));
    }

    if (has_property(KW_READREPAIRCHANCE)) {
        builder.set_read_repair_chance(get_double(KW_READREPAIRCHANCE, builder.get_read_repair_chance()));
    }

    if (has_property(KW_DCLOCALREADREPAIRCHANCE)) {
        builder.set_dc_local_read_repair_chance(get_double(KW_DCLOCALREADREPAIRCHANCE, builder.get_dc_local_read_repair_chance()));
    }

    if (has_property(KW_GCGRACESECONDS)) {
        builder.set_gc_grace_seconds(get_int(KW_GCGRACESECONDS, builder.get_gc_grace_seconds()));
    }

    std::experimental::optional<sstring> tmp_value = {};
    if (has_property(KW_COMPACTION)) {
        if (get_compaction_options().count(KW_MINCOMPACTIONTHRESHOLD)) {
            tmp_value = get_compaction_options().at(KW_MINCOMPACTIONTHRESHOLD);
        }
    }
    int min_compaction_threshold = to_int(KW_MINCOMPACTIONTHRESHOLD, tmp_value, builder.get_min_compaction_threshold());

    tmp_value = {};
    if (has_property(KW_COMPACTION)) {
        if (get_compaction_options().count(KW_MAXCOMPACTIONTHRESHOLD)) {
            tmp_value = get_compaction_options().at(KW_MAXCOMPACTIONTHRESHOLD);
        }
    }
    int max_compaction_threshold = to_int(KW_MAXCOMPACTIONTHRESHOLD, tmp_value, builder.get_max_compaction_threshold());

    if (min_compaction_threshold <= 0 || max_compaction_threshold <= 0)
        throw exceptions::configuration_exception("Disabling compaction by setting compaction thresholds to 0 has been deprecated, set the compaction option 'enabled' to false instead.");
    builder.set_min_compaction_threshold(min_compaction_threshold);
    builder.set_max_compaction_threshold(max_compaction_threshold);

    builder.set_default_time_to_live(gc_clock::duration(get_int(KW_DEFAULT_TIME_TO_LIVE, DEFAULT_DEFAULT_TIME_TO_LIVE)));

    if (has_property(KW_SPECULATIVE_RETRY)) {
        builder.set_speculative_retry(get_string(KW_SPECULATIVE_RETRY, builder.get_speculative_retry().to_sstring()));
    }

    if (has_property(KW_MEMTABLE_FLUSH_PERIOD)) {
        builder.set_memtable_flush_period(get_int(KW_MEMTABLE_FLUSH_PERIOD, builder.get_memtable_flush_period()));
    }

    if (has_property(KW_MIN_INDEX_INTERVAL)) {
        builder.set_min_index_interval(get_int(KW_MIN_INDEX_INTERVAL, builder.get_min_index_interval()));
    }

    if (has_property(KW_MAX_INDEX_INTERVAL)) {
        builder.set_max_index_interval(get_int(KW_MAX_INDEX_INTERVAL, builder.get_max_index_interval()));
    }

    if (_compaction_strategy_class) {
        builder.set_compaction_strategy(*_compaction_strategy_class);
        builder.set_compaction_strategy_options(get_compaction_options());
    }

    builder.set_bloom_filter_fp_chance(get_double(KW_BF_FP_CHANCE, builder.get_bloom_filter_fp_chance()));
    if (!get_compression_options().empty()) {
        builder.set_compressor_params(compression_parameters(get_compression_options()));
    }
#if 0
    CachingOptions cachingOptions = getCachingOptions();
    if (cachingOptions != null)
        cfm.caching(cachingOptions);
#endif
}

void cf_prop_defs::validate_minimum_int(const sstring& field, int32_t minimum_value, int32_t default_value) const
{
    auto val = get_int(field, default_value);
    if (val < minimum_value) {
        throw exceptions::configuration_exception(sprint("%s cannot be smaller than %s, (default %s)",
                                                         field, minimum_value, default_value));
    }
}

}

}
<|endoftext|>


<commit_before>//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the MemoryBuffer interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/system_error.h"
#include <cassert>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <new>
#include <sys/stat.h>
#include <sys/types.h>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#else
#include <io.h>
// Simplistic definitinos of these macros for use in getOpenFile.
#ifndef S_ISREG
#define S_ISREG(x) (1)
#endif
#ifndef S_ISBLK
#define S_ISBLK(x) (0)
#endif
#endif
#include <fcntl.h>
using namespace llvm;

//===----------------------------------------------------------------------===//
// MemoryBuffer implementation itself.
//===----------------------------------------------------------------------===//

MemoryBuffer::~MemoryBuffer() { }

/// init - Initialize this MemoryBuffer as a reference to externally allocated
/// memory, memory that we know is already null terminated.
void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
                        bool RequiresNullTerminator) {
  assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
         "Buffer is not null terminated!");
  BufferStart = BufStart;
  BufferEnd = BufEnd;
}

//===----------------------------------------------------------------------===//
// MemoryBufferMem implementation.
//===----------------------------------------------------------------------===//

/// CopyStringRef - Copies contents of a StringRef into a block of memory and
/// null-terminates it.
static void CopyStringRef(char *Memory, StringRef Data) {
  memcpy(Memory, Data.data(), Data.size());
  Memory[Data.size()] = 0; // Null terminate string.
}

namespace {
struct NamedBufferAlloc {
  StringRef Name;
  NamedBufferAlloc(StringRef Name) : Name(Name) {}
};
}

void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
  char *Mem = static_cast<char *>(operator new(N + Alloc.Name.size() + 1));
  CopyStringRef(Mem + N, Alloc.Name);
  return Mem;
}

namespace {
/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
class MemoryBufferMem : public MemoryBuffer {
public:
  MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
    init(InputData.begin(), InputData.end(), RequiresNullTerminator);
  }

  virtual const char *getBufferIdentifier() const LLVM_OVERRIDE {
     // The name is stored after the class itself.
    return reinterpret_cast<const char*>(this + 1);
  }

  virtual BufferKind getBufferKind() const LLVM_OVERRIDE {
    return MemoryBuffer_Malloc;
  }
};
}

/// getMemBuffer - Open the specified memory range as a MemoryBuffer.  Note
/// that InputData must be a null terminated if RequiresNullTerminator is true!
MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
                                         StringRef BufferName,
                                         bool RequiresNullTerminator) {
  return new (NamedBufferAlloc(BufferName))
      MemoryBufferMem(InputData, RequiresNullTerminator);
}

/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
/// copying the contents and taking ownership of it.  This has no requirements
/// on EndPtr[0].
MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData,
                                             StringRef BufferName) {
  MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName);
  if (!Buf) return 0;
  memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
         InputData.size());
  return Buf;
}

/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
/// that is not initialized.  Note that the caller should initialize the
/// memory allocated by this method.  The memory is owned by the MemoryBuffer
/// object.
MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,
                                                  StringRef BufferName) {
  // Allocate space for the MemoryBuffer, the data and the name. It is important
  // that MemoryBuffer and data are aligned so PointerIntPair works with them.
  size_t AlignedStringLen =
    RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1,
                       sizeof(void*)); // TODO: Is sizeof(void*) enough?
  size_t RealLen = AlignedStringLen + Size + 1;
  char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
  if (!Mem) return 0;

  // The name is stored after the class itself.
  CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName);

  // The buffer begins after the name and must be aligned.
  char *Buf = Mem + AlignedStringLen;
  Buf[Size] = 0; // Null terminate buffer.

  return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
}

/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
/// is completely initialized to zeros.  Note that the caller should
/// initialize the memory allocated by this method.  The memory is owned by
/// the MemoryBuffer object.
MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
  MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName);
  if (!SB) return 0;
  memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
  return SB;
}

/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin
/// if the Filename is "-".  If an error occurs, this returns null and fills
/// in *ErrStr with a reason.  If stdin is empty, this API (unlike getSTDIN)
/// returns an empty buffer.
error_code MemoryBuffer::getFileOrSTDIN(StringRef Filename,
                                        OwningPtr<MemoryBuffer> &result,
                                        int64_t FileSize) {
  if (Filename == "-")
    return getSTDIN(result);
  return getFile(Filename, result, FileSize);
}

//===----------------------------------------------------------------------===//
// MemoryBuffer::getFile implementation.
//===----------------------------------------------------------------------===//

namespace {
/// \brief Memorry maps a file descriptor using sys::fs::mapped_file_region.
///
/// This handles converting the offset into a legal offset on the platform.
class MemoryBufferMMapFile : public MemoryBuffer {
  sys::fs::mapped_file_region MFR;

  static uint64_t getLegalMapOffset(uint64_t Offset) {
    return Offset & ~(sys::fs::mapped_file_region::alignment() - 1);
  }

  static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
    return Len + (Offset - getLegalMapOffset(Offset));
  }

  const char *getStart(uint64_t Len, uint64_t Offset) {
    return MFR.const_data() + (Offset - getLegalMapOffset(Offset));
  }

public:
  MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len,
                       uint64_t Offset, error_code EC)
      : MFR(FD, false, sys::fs::mapped_file_region::readonly,
            getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) {
    if (!EC) {
      const char *Start = getStart(Len, Offset);
      init(Start, Start + Len, RequiresNullTerminator);
    }
  }

  virtual const char *getBufferIdentifier() const LLVM_OVERRIDE {
    // The name is stored after the class itself.
    return reinterpret_cast<const char *>(this + 1);
  }

  virtual BufferKind getBufferKind() const LLVM_OVERRIDE {
    return MemoryBuffer_MMap;
  }
};
}

static error_code getMemoryBufferForStream(int FD,
                                           StringRef BufferName,
                                           OwningPtr<MemoryBuffer> &result) {
  const ssize_t ChunkSize = 4096*4;
  SmallString<ChunkSize> Buffer;
  ssize_t ReadBytes;
  // Read into Buffer until we hit EOF.
  do {
    Buffer.reserve(Buffer.size() + ChunkSize);
    ReadBytes = read(FD, Buffer.end(), ChunkSize);
    if (ReadBytes == -1) {
      if (errno == EINTR) continue;
      return error_code(errno, posix_category());
    }
    Buffer.set_size(Buffer.size() + ReadBytes);
  } while (ReadBytes != 0);

  result.reset(MemoryBuffer::getMemBufferCopy(Buffer, BufferName));
  return error_code::success();
}

error_code MemoryBuffer::getFile(StringRef Filename,
                                 OwningPtr<MemoryBuffer> &result,
                                 int64_t FileSize,
                                 bool RequiresNullTerminator) {
  // Ensure the path is null terminated.
  SmallString<256> PathBuf(Filename.begin(), Filename.end());
  return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize,
                               RequiresNullTerminator);
}

error_code MemoryBuffer::getFile(const char *Filename,
                                 OwningPtr<MemoryBuffer> &result,
                                 int64_t FileSize,
                                 bool RequiresNullTerminator) {
  // FIXME: Review if this check is unnecessary on windows as well.
#ifdef LLVM_ON_WIN32
  // First check that the "file" is not a directory
  bool is_dir = false;
  error_code err = sys::fs::is_directory(Filename, is_dir);
  if (err)
    return err;
  if (is_dir)
    return make_error_code(errc::is_a_directory);
#endif

  int OpenFlags = O_RDONLY;
#ifdef O_BINARY
  OpenFlags |= O_BINARY;  // Open input file in binary mode on win32.
#endif
  int FD = ::open(Filename, OpenFlags);
  if (FD == -1)
    return error_code(errno, posix_category());

  error_code ret = getOpenFile(FD, Filename, result, FileSize, FileSize,
                               0, RequiresNullTerminator);
  close(FD);
  return ret;
}

static bool shouldUseMmap(int FD,
                          size_t FileSize,
                          size_t MapSize,
                          off_t Offset,
                          bool RequiresNullTerminator,
                          int PageSize) {
  // We don't use mmap for small files because this can severely fragment our
  // address space.
  if (MapSize < 4096*4)
    return false;

  if (!RequiresNullTerminator)
    return true;

  // If we don't know the file size, use fstat to find out.  fstat on an open
  // file descriptor is cheaper than stat on a random path.
  // FIXME: this chunk of code is duplicated, but it avoids a fstat when
  // RequiresNullTerminator = false and MapSize != -1.
  if (FileSize == size_t(-1)) {
    struct stat FileInfo;
    // TODO: This should use fstat64 when available.
    if (fstat(FD, &FileInfo) == -1) {
      return error_code(errno, posix_category());
    }
    FileSize = FileInfo.st_size;
  }

  // If we need a null terminator and the end of the map is inside the file,
  // we cannot use mmap.
  size_t End = Offset + MapSize;
  assert(End <= FileSize);
  if (End != FileSize)
    return false;

  // Don't try to map files that are exactly a multiple of the system page size
  // if we need a null terminator.
  if ((FileSize & (PageSize -1)) == 0)
    return false;

  return true;
}

error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
                                     OwningPtr<MemoryBuffer> &result,
                                     uint64_t FileSize, uint64_t MapSize,
                                     int64_t Offset,
                                     bool RequiresNullTerminator) {
  static int PageSize = sys::process::get_self()->page_size();

  // Default is to map the full file.
  if (MapSize == uint64_t(-1)) {
    // If we don't know the file size, use fstat to find out.  fstat on an open
    // file descriptor is cheaper than stat on a random path.
    if (FileSize == uint64_t(-1)) {
      struct stat FileInfo;
      // TODO: This should use fstat64 when available.
      if (fstat(FD, &FileInfo) == -1) {
        return error_code(errno, posix_category());
      }

      // If this not a file or a block device (e.g. it's a named pipe
      // or character device), we can't trust the size. Create the memory
      // buffer by copying off the stream.
      if (!S_ISREG(FileInfo.st_mode) && !S_ISBLK(FileInfo.st_mode)) {
        return getMemoryBufferForStream(FD, Filename, result);
      }

      FileSize = FileInfo.st_size;
    }
    MapSize = FileSize;
  }

  if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
                    PageSize)) {
    error_code EC;
    result.reset(new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile(
        RequiresNullTerminator, FD, MapSize, Offset, EC));
    if (!EC)
      return error_code::success();
  }

  MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
  if (!Buf) {
    // Failed to create a buffer. The only way it can fail is if
    // new(std::nothrow) returns 0.
    return make_error_code(errc::not_enough_memory);
  }

  OwningPtr<MemoryBuffer> SB(Buf);
  char *BufPtr = const_cast<char*>(SB->getBufferStart());

  size_t BytesLeft = MapSize;
#ifndef HAVE_PREAD
  if (lseek(FD, Offset, SEEK_SET) == -1)
    return error_code(errno, posix_category());
#endif

  while (BytesLeft) {
#ifdef HAVE_PREAD
    ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
#else
    ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
#endif
    if (NumRead == -1) {
      if (errno == EINTR)
        continue;
      // Error while reading.
      return error_code(errno, posix_category());
    }
    if (NumRead == 0) {
      assert(0 && "We got inaccurate FileSize value or fstat reported an "
                   "invalid file size.");
      *BufPtr = '\0'; // null-terminate at the actual size.
      break;
    }
    BytesLeft -= NumRead;
    BufPtr += NumRead;
  }

  result.swap(SB);
  return error_code::success();
}

//===----------------------------------------------------------------------===//
// MemoryBuffer::getSTDIN implementation.
//===----------------------------------------------------------------------===//

error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) {
  // Read in all of the data from stdin, we cannot mmap stdin.
  //
  // FIXME: That isn't necessarily true, we should try to mmap stdin and
  // fallback if it fails.
  sys::ChangeStdinToBinary();

  return getMemoryBufferForStream(0, "<stdin>", result);
}
<commit_msg>Remove an extra is_directory call.<commit_after>//===--- MemoryBuffer.cpp - Memory Buffer implementation ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the MemoryBuffer interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/system_error.h"
#include <cassert>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <new>
#include <sys/stat.h>
#include <sys/types.h>
#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#else
#include <io.h>
// Simplistic definitinos of these macros for use in getOpenFile.
#ifndef S_ISREG
#define S_ISREG(x) (1)
#endif
#ifndef S_ISBLK
#define S_ISBLK(x) (0)
#endif
#endif
#include <fcntl.h>
using namespace llvm;

//===----------------------------------------------------------------------===//
// MemoryBuffer implementation itself.
//===----------------------------------------------------------------------===//

MemoryBuffer::~MemoryBuffer() { }

/// init - Initialize this MemoryBuffer as a reference to externally allocated
/// memory, memory that we know is already null terminated.
void MemoryBuffer::init(const char *BufStart, const char *BufEnd,
                        bool RequiresNullTerminator) {
  assert((!RequiresNullTerminator || BufEnd[0] == 0) &&
         "Buffer is not null terminated!");
  BufferStart = BufStart;
  BufferEnd = BufEnd;
}

//===----------------------------------------------------------------------===//
// MemoryBufferMem implementation.
//===----------------------------------------------------------------------===//

/// CopyStringRef - Copies contents of a StringRef into a block of memory and
/// null-terminates it.
static void CopyStringRef(char *Memory, StringRef Data) {
  memcpy(Memory, Data.data(), Data.size());
  Memory[Data.size()] = 0; // Null terminate string.
}

namespace {
struct NamedBufferAlloc {
  StringRef Name;
  NamedBufferAlloc(StringRef Name) : Name(Name) {}
};
}

void *operator new(size_t N, const NamedBufferAlloc &Alloc) {
  char *Mem = static_cast<char *>(operator new(N + Alloc.Name.size() + 1));
  CopyStringRef(Mem + N, Alloc.Name);
  return Mem;
}

namespace {
/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.
class MemoryBufferMem : public MemoryBuffer {
public:
  MemoryBufferMem(StringRef InputData, bool RequiresNullTerminator) {
    init(InputData.begin(), InputData.end(), RequiresNullTerminator);
  }

  virtual const char *getBufferIdentifier() const LLVM_OVERRIDE {
     // The name is stored after the class itself.
    return reinterpret_cast<const char*>(this + 1);
  }

  virtual BufferKind getBufferKind() const LLVM_OVERRIDE {
    return MemoryBuffer_Malloc;
  }
};
}

/// getMemBuffer - Open the specified memory range as a MemoryBuffer.  Note
/// that InputData must be a null terminated if RequiresNullTerminator is true!
MemoryBuffer *MemoryBuffer::getMemBuffer(StringRef InputData,
                                         StringRef BufferName,
                                         bool RequiresNullTerminator) {
  return new (NamedBufferAlloc(BufferName))
      MemoryBufferMem(InputData, RequiresNullTerminator);
}

/// getMemBufferCopy - Open the specified memory range as a MemoryBuffer,
/// copying the contents and taking ownership of it.  This has no requirements
/// on EndPtr[0].
MemoryBuffer *MemoryBuffer::getMemBufferCopy(StringRef InputData,
                                             StringRef BufferName) {
  MemoryBuffer *Buf = getNewUninitMemBuffer(InputData.size(), BufferName);
  if (!Buf) return 0;
  memcpy(const_cast<char*>(Buf->getBufferStart()), InputData.data(),
         InputData.size());
  return Buf;
}

/// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size
/// that is not initialized.  Note that the caller should initialize the
/// memory allocated by this method.  The memory is owned by the MemoryBuffer
/// object.
MemoryBuffer *MemoryBuffer::getNewUninitMemBuffer(size_t Size,
                                                  StringRef BufferName) {
  // Allocate space for the MemoryBuffer, the data and the name. It is important
  // that MemoryBuffer and data are aligned so PointerIntPair works with them.
  size_t AlignedStringLen =
    RoundUpToAlignment(sizeof(MemoryBufferMem) + BufferName.size() + 1,
                       sizeof(void*)); // TODO: Is sizeof(void*) enough?
  size_t RealLen = AlignedStringLen + Size + 1;
  char *Mem = static_cast<char*>(operator new(RealLen, std::nothrow));
  if (!Mem) return 0;

  // The name is stored after the class itself.
  CopyStringRef(Mem + sizeof(MemoryBufferMem), BufferName);

  // The buffer begins after the name and must be aligned.
  char *Buf = Mem + AlignedStringLen;
  Buf[Size] = 0; // Null terminate buffer.

  return new (Mem) MemoryBufferMem(StringRef(Buf, Size), true);
}

/// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that
/// is completely initialized to zeros.  Note that the caller should
/// initialize the memory allocated by this method.  The memory is owned by
/// the MemoryBuffer object.
MemoryBuffer *MemoryBuffer::getNewMemBuffer(size_t Size, StringRef BufferName) {
  MemoryBuffer *SB = getNewUninitMemBuffer(Size, BufferName);
  if (!SB) return 0;
  memset(const_cast<char*>(SB->getBufferStart()), 0, Size);
  return SB;
}

/// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin
/// if the Filename is "-".  If an error occurs, this returns null and fills
/// in *ErrStr with a reason.  If stdin is empty, this API (unlike getSTDIN)
/// returns an empty buffer.
error_code MemoryBuffer::getFileOrSTDIN(StringRef Filename,
                                        OwningPtr<MemoryBuffer> &result,
                                        int64_t FileSize) {
  if (Filename == "-")
    return getSTDIN(result);
  return getFile(Filename, result, FileSize);
}

//===----------------------------------------------------------------------===//
// MemoryBuffer::getFile implementation.
//===----------------------------------------------------------------------===//

namespace {
/// \brief Memorry maps a file descriptor using sys::fs::mapped_file_region.
///
/// This handles converting the offset into a legal offset on the platform.
class MemoryBufferMMapFile : public MemoryBuffer {
  sys::fs::mapped_file_region MFR;

  static uint64_t getLegalMapOffset(uint64_t Offset) {
    return Offset & ~(sys::fs::mapped_file_region::alignment() - 1);
  }

  static uint64_t getLegalMapSize(uint64_t Len, uint64_t Offset) {
    return Len + (Offset - getLegalMapOffset(Offset));
  }

  const char *getStart(uint64_t Len, uint64_t Offset) {
    return MFR.const_data() + (Offset - getLegalMapOffset(Offset));
  }

public:
  MemoryBufferMMapFile(bool RequiresNullTerminator, int FD, uint64_t Len,
                       uint64_t Offset, error_code EC)
      : MFR(FD, false, sys::fs::mapped_file_region::readonly,
            getLegalMapSize(Len, Offset), getLegalMapOffset(Offset), EC) {
    if (!EC) {
      const char *Start = getStart(Len, Offset);
      init(Start, Start + Len, RequiresNullTerminator);
    }
  }

  virtual const char *getBufferIdentifier() const LLVM_OVERRIDE {
    // The name is stored after the class itself.
    return reinterpret_cast<const char *>(this + 1);
  }

  virtual BufferKind getBufferKind() const LLVM_OVERRIDE {
    return MemoryBuffer_MMap;
  }
};
}

static error_code getMemoryBufferForStream(int FD,
                                           StringRef BufferName,
                                           OwningPtr<MemoryBuffer> &result) {
  const ssize_t ChunkSize = 4096*4;
  SmallString<ChunkSize> Buffer;
  ssize_t ReadBytes;
  // Read into Buffer until we hit EOF.
  do {
    Buffer.reserve(Buffer.size() + ChunkSize);
    ReadBytes = read(FD, Buffer.end(), ChunkSize);
    if (ReadBytes == -1) {
      if (errno == EINTR) continue;
      return error_code(errno, posix_category());
    }
    Buffer.set_size(Buffer.size() + ReadBytes);
  } while (ReadBytes != 0);

  result.reset(MemoryBuffer::getMemBufferCopy(Buffer, BufferName));
  return error_code::success();
}

error_code MemoryBuffer::getFile(StringRef Filename,
                                 OwningPtr<MemoryBuffer> &result,
                                 int64_t FileSize,
                                 bool RequiresNullTerminator) {
  // Ensure the path is null terminated.
  SmallString<256> PathBuf(Filename.begin(), Filename.end());
  return MemoryBuffer::getFile(PathBuf.c_str(), result, FileSize,
                               RequiresNullTerminator);
}

error_code MemoryBuffer::getFile(const char *Filename,
                                 OwningPtr<MemoryBuffer> &result,
                                 int64_t FileSize,
                                 bool RequiresNullTerminator) {
  int OpenFlags = O_RDONLY;
#ifdef O_BINARY
  OpenFlags |= O_BINARY;  // Open input file in binary mode on win32.
#endif
  int FD = ::open(Filename, OpenFlags);
  if (FD == -1)
    return error_code(errno, posix_category());

  error_code ret = getOpenFile(FD, Filename, result, FileSize, FileSize,
                               0, RequiresNullTerminator);
  close(FD);
  return ret;
}

static bool shouldUseMmap(int FD,
                          size_t FileSize,
                          size_t MapSize,
                          off_t Offset,
                          bool RequiresNullTerminator,
                          int PageSize) {
  // We don't use mmap for small files because this can severely fragment our
  // address space.
  if (MapSize < 4096*4)
    return false;

  if (!RequiresNullTerminator)
    return true;

  // If we don't know the file size, use fstat to find out.  fstat on an open
  // file descriptor is cheaper than stat on a random path.
  // FIXME: this chunk of code is duplicated, but it avoids a fstat when
  // RequiresNullTerminator = false and MapSize != -1.
  if (FileSize == size_t(-1)) {
    struct stat FileInfo;
    // TODO: This should use fstat64 when available.
    if (fstat(FD, &FileInfo) == -1) {
      return error_code(errno, posix_category());
    }
    FileSize = FileInfo.st_size;
  }

  // If we need a null terminator and the end of the map is inside the file,
  // we cannot use mmap.
  size_t End = Offset + MapSize;
  assert(End <= FileSize);
  if (End != FileSize)
    return false;

  // Don't try to map files that are exactly a multiple of the system page size
  // if we need a null terminator.
  if ((FileSize & (PageSize -1)) == 0)
    return false;

  return true;
}

error_code MemoryBuffer::getOpenFile(int FD, const char *Filename,
                                     OwningPtr<MemoryBuffer> &result,
                                     uint64_t FileSize, uint64_t MapSize,
                                     int64_t Offset,
                                     bool RequiresNullTerminator) {
  static int PageSize = sys::process::get_self()->page_size();

  // Default is to map the full file.
  if (MapSize == uint64_t(-1)) {
    // If we don't know the file size, use fstat to find out.  fstat on an open
    // file descriptor is cheaper than stat on a random path.
    if (FileSize == uint64_t(-1)) {
      struct stat FileInfo;
      // TODO: This should use fstat64 when available.
      if (fstat(FD, &FileInfo) == -1) {
        return error_code(errno, posix_category());
      }

      // If this not a file or a block device (e.g. it's a named pipe
      // or character device), we can't trust the size. Create the memory
      // buffer by copying off the stream.
      if (!S_ISREG(FileInfo.st_mode) && !S_ISBLK(FileInfo.st_mode)) {
        return getMemoryBufferForStream(FD, Filename, result);
      }

      FileSize = FileInfo.st_size;
    }
    MapSize = FileSize;
  }

  if (shouldUseMmap(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
                    PageSize)) {
    error_code EC;
    result.reset(new (NamedBufferAlloc(Filename)) MemoryBufferMMapFile(
        RequiresNullTerminator, FD, MapSize, Offset, EC));
    if (!EC)
      return error_code::success();
  }

  MemoryBuffer *Buf = MemoryBuffer::getNewUninitMemBuffer(MapSize, Filename);
  if (!Buf) {
    // Failed to create a buffer. The only way it can fail is if
    // new(std::nothrow) returns 0.
    return make_error_code(errc::not_enough_memory);
  }

  OwningPtr<MemoryBuffer> SB(Buf);
  char *BufPtr = const_cast<char*>(SB->getBufferStart());

  size_t BytesLeft = MapSize;
#ifndef HAVE_PREAD
  if (lseek(FD, Offset, SEEK_SET) == -1)
    return error_code(errno, posix_category());
#endif

  while (BytesLeft) {
#ifdef HAVE_PREAD
    ssize_t NumRead = ::pread(FD, BufPtr, BytesLeft, MapSize-BytesLeft+Offset);
#else
    ssize_t NumRead = ::read(FD, BufPtr, BytesLeft);
#endif
    if (NumRead == -1) {
      if (errno == EINTR)
        continue;
      // Error while reading.
      return error_code(errno, posix_category());
    }
    if (NumRead == 0) {
      assert(0 && "We got inaccurate FileSize value or fstat reported an "
                   "invalid file size.");
      *BufPtr = '\0'; // null-terminate at the actual size.
      break;
    }
    BytesLeft -= NumRead;
    BufPtr += NumRead;
  }

  result.swap(SB);
  return error_code::success();
}

//===----------------------------------------------------------------------===//
// MemoryBuffer::getSTDIN implementation.
//===----------------------------------------------------------------------===//

error_code MemoryBuffer::getSTDIN(OwningPtr<MemoryBuffer> &result) {
  // Read in all of the data from stdin, we cannot mmap stdin.
  //
  // FIXME: That isn't necessarily true, we should try to mmap stdin and
  // fallback if it fails.
  sys::ChangeStdinToBinary();

  return getMemoryBufferForStream(0, "<stdin>", result);
}
<|endoftext|>


<commit_before>//===-- TargetMachine.cpp - General Target Information ---------------------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the general parts of a Target machine.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Type.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

//---------------------------------------------------------------------------
// Command-line options that tend to be useful on more than one back-end.
//

namespace llvm {
  bool PrintMachineCode;
  bool NoFramePointerElim;
  bool NoExcessFPPrecision;
  bool UnsafeFPMath;
  bool FiniteOnlyFPMathOption;
  Reloc::Model RelocationModel;
  CodeModel::Model CMModel;
}
namespace {
  cl::opt<bool, true> PrintCode("print-machineinstrs",
    cl::desc("Print generated machine code"),
    cl::location(PrintMachineCode), cl::init(false));

  cl::opt<bool, true>
    DisableFPElim("disable-fp-elim",
                  cl::desc("Disable frame pointer elimination optimization"),
                  cl::location(NoFramePointerElim),
                  cl::init(false));
  cl::opt<bool, true>
  DisableExcessPrecision("disable-excess-fp-precision",
               cl::desc("Disable optimizations that may increase FP precision"),
               cl::location(NoExcessFPPrecision),
               cl::init(false));
  cl::opt<bool, true>
  EnableUnsafeFPMath("enable-unsafe-fp-math",
               cl::desc("Enable optimizations that may decrease FP precision"),
               cl::location(UnsafeFPMath),
               cl::init(false));
  cl::opt<bool, true>
  EnableFiniteOnltFPMath("enable-finite-only-fp-math",
               cl::desc("Enable optimizations that assumes non- NaNs / +-Infs"),
               cl::location(FiniteOnlyFPMathOption),
               cl::init(false));
  cl::opt<llvm::Reloc::Model, true>
  DefRelocationModel(
    "relocation-model",
    cl::desc("Choose relocation model"),
    cl::location(RelocationModel),
    cl::init(Reloc::Default),
    cl::values(
      clEnumValN(Reloc::Default, "default",
                 "  Target default relocation model"),
      clEnumValN(Reloc::Static, "static",
                 "  Non-relocatable code"),
      clEnumValN(Reloc::PIC_, "pic",
                 "  Fully relocatable, position independent code"),
      clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
                 "  Relocatable external references, non-relocatable code"),
      clEnumValEnd));
  cl::opt<llvm::CodeModel::Model, true>
  DefCodeModel(
    "code-model",
    cl::desc("Choose relocation model"),
    cl::location(CMModel),
    cl::init(CodeModel::Default),
    cl::values(
      clEnumValN(CodeModel::Default, "default",
                 "  Target default code model"),
      clEnumValN(CodeModel::Small, "small",
                 "  Small code model"),
      clEnumValN(CodeModel::Kernel, "kernel",
                 "  Kernel code model"),
      clEnumValN(CodeModel::Medium, "medium",
                 "  Medium code model"),
      clEnumValN(CodeModel::Large, "large",
                 "  Large code model"),
      clEnumValEnd));
}

//---------------------------------------------------------------------------
// TargetMachine Class
//

TargetMachine::~TargetMachine() {
}

/// getRelocationModel - Returns the code generation relocation model. The
/// choices are static, PIC, and dynamic-no-pic, and target default.
Reloc::Model TargetMachine::getRelocationModel() {
  return RelocationModel;
}

/// setRelocationModel - Sets the code generation relocation model.
void TargetMachine::setRelocationModel(Reloc::Model Model) {
  RelocationModel = Model;
}

/// getCodeModel - Returns the code model. The choices are small, kernel,
/// medium, large, and target default.
CodeModel::Model TargetMachine::getCodeModel() {
  return CMModel;
}

/// setCodeModel - Sets the code model.
void TargetMachine::setCodeModel(CodeModel::Model Model) {
  CMModel = Model;
}

namespace llvm {
  /// FiniteOnlyFPMath - This returns true when the -enable-finite-only-fp-math
  /// option is specified on the command line. If this returns false (default),
  /// the code generator is not allowed to assume that FP arithmetic arguments
  /// and results are never NaNs or +-Infs.
  bool FiniteOnlyFPMath() { return UnsafeFPMath || FiniteOnlyFPMathOption; }
}
<commit_msg>remove #include<commit_after>//===-- TargetMachine.cpp - General Target Information ---------------------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file describes the general parts of a Target machine.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;

//---------------------------------------------------------------------------
// Command-line options that tend to be useful on more than one back-end.
//

namespace llvm {
  bool PrintMachineCode;
  bool NoFramePointerElim;
  bool NoExcessFPPrecision;
  bool UnsafeFPMath;
  bool FiniteOnlyFPMathOption;
  Reloc::Model RelocationModel;
  CodeModel::Model CMModel;
}
namespace {
  cl::opt<bool, true> PrintCode("print-machineinstrs",
    cl::desc("Print generated machine code"),
    cl::location(PrintMachineCode), cl::init(false));

  cl::opt<bool, true>
    DisableFPElim("disable-fp-elim",
                  cl::desc("Disable frame pointer elimination optimization"),
                  cl::location(NoFramePointerElim),
                  cl::init(false));
  cl::opt<bool, true>
  DisableExcessPrecision("disable-excess-fp-precision",
               cl::desc("Disable optimizations that may increase FP precision"),
               cl::location(NoExcessFPPrecision),
               cl::init(false));
  cl::opt<bool, true>
  EnableUnsafeFPMath("enable-unsafe-fp-math",
               cl::desc("Enable optimizations that may decrease FP precision"),
               cl::location(UnsafeFPMath),
               cl::init(false));
  cl::opt<bool, true>
  EnableFiniteOnltFPMath("enable-finite-only-fp-math",
               cl::desc("Enable optimizations that assumes non- NaNs / +-Infs"),
               cl::location(FiniteOnlyFPMathOption),
               cl::init(false));
  cl::opt<llvm::Reloc::Model, true>
  DefRelocationModel(
    "relocation-model",
    cl::desc("Choose relocation model"),
    cl::location(RelocationModel),
    cl::init(Reloc::Default),
    cl::values(
      clEnumValN(Reloc::Default, "default",
                 "  Target default relocation model"),
      clEnumValN(Reloc::Static, "static",
                 "  Non-relocatable code"),
      clEnumValN(Reloc::PIC_, "pic",
                 "  Fully relocatable, position independent code"),
      clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
                 "  Relocatable external references, non-relocatable code"),
      clEnumValEnd));
  cl::opt<llvm::CodeModel::Model, true>
  DefCodeModel(
    "code-model",
    cl::desc("Choose relocation model"),
    cl::location(CMModel),
    cl::init(CodeModel::Default),
    cl::values(
      clEnumValN(CodeModel::Default, "default",
                 "  Target default code model"),
      clEnumValN(CodeModel::Small, "small",
                 "  Small code model"),
      clEnumValN(CodeModel::Kernel, "kernel",
                 "  Kernel code model"),
      clEnumValN(CodeModel::Medium, "medium",
                 "  Medium code model"),
      clEnumValN(CodeModel::Large, "large",
                 "  Large code model"),
      clEnumValEnd));
}

//---------------------------------------------------------------------------
// TargetMachine Class
//

TargetMachine::~TargetMachine() {
}

/// getRelocationModel - Returns the code generation relocation model. The
/// choices are static, PIC, and dynamic-no-pic, and target default.
Reloc::Model TargetMachine::getRelocationModel() {
  return RelocationModel;
}

/// setRelocationModel - Sets the code generation relocation model.
void TargetMachine::setRelocationModel(Reloc::Model Model) {
  RelocationModel = Model;
}

/// getCodeModel - Returns the code model. The choices are small, kernel,
/// medium, large, and target default.
CodeModel::Model TargetMachine::getCodeModel() {
  return CMModel;
}

/// setCodeModel - Sets the code model.
void TargetMachine::setCodeModel(CodeModel::Model Model) {
  CMModel = Model;
}

namespace llvm {
  /// FiniteOnlyFPMath - This returns true when the -enable-finite-only-fp-math
  /// option is specified on the command line. If this returns false (default),
  /// the code generator is not allowed to assume that FP arithmetic arguments
  /// and results are never NaNs or +-Infs.
  bool FiniteOnlyFPMath() { return UnsafeFPMath || FiniteOnlyFPMathOption; }
}

<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <cctype>

#include <commons/Types.h>
#include <commons/Utils.h>

#include "Parser.h"
#include "Operators.h"

using std::string;
using std::ios_base;

Program* Parser::parse() throw (CompilerException) {
	Program* program = new Program();

	while(lexer.next()){
		if(!lexer.isWord()){
			throw CompilerException("An instruction can only start with a call or an assignation");
		}

		string word = lexer.getCurrentToken();

		if(!lexer.next()){
			throw CompilerException("Incomplete instruction");
		}

		if(lexer.isLeftParenth()){ //is a call
			parseCall(program, word);
		} else if(lexer.isWord()){ //is a declaration
			parseDeclaration(program, word);
		} else if(lexer.isAssign()){ //is an assign
			parseAssignment(program, word);
		} else {
			throw CompilerException("Not an instruction");
		}
	}

	return program;
}

ParseNode* readValue(Lexer& lexer){
	if(!lexer.next()){
		throw CompilerException("Waiting for a value");
	}

	ParseNode* node = NULL;

	if(lexer.isLitteral()){
		string litteral = lexer.getCurrentToken();

		node = new Litteral(litteral);
	} else if(lexer.isWord()){
		string variableRight = lexer.getCurrentToken();

		node = new VariableValue(variableRight);
	} else if(lexer.isInteger()){
		string integer = lexer.getCurrentToken();
		int value = toNumber<int>(integer);

		node = new Integer(value);
	}

	lexer.next();

	if(lexer.isAddition()){
		ParseNode* add = new Addition();

		add->addLast(node);
		add->addLast(readValue(lexer));

		return add;
	} else if(lexer.isSubtraction()){
		ParseNode* subtract = new Subtraction();

		subtract->addLast(node);
		subtract->addLast(readValue(lexer));

		return subtract;
	} else {
		lexer.pushBack();
	}

	return node;
}

void Parser::parseCall(Program* program, string call) throw (CompilerException){
	if(call != "Print"){
		throw CompilerException("The call \"" + call + "\" does not exist");
	}

	ParseNode* value = readValue(lexer);

	if(!lexer.next() || !lexer.isRightParenth()){
		throw CompilerException("The call must be closed with a right parenth");
	}

	if(!lexer.next() || !lexer.isStop()){
		throw CompilerException("Every instruction must be closed by a semicolon");
	}

	Print* print = new Print();

	print->addLast(value);

	program->addLast(print);
}

void Parser::parseDeclaration(Program* program, string typeName) throw (CompilerException){
	if(typeName != "int" && typeName != "string"){
		throw CompilerException("Invalid type");
	}

	Type type;
	if(typeName == "int"){
		type = INT;
	} else {
		type = STRING;
	}

	string variable = lexer.getCurrentToken();

	if(!lexer.next() || !lexer.isAssign()){
		throw CompilerException("A variable declaration must followed by '='");
	}

	ParseNode* value = readValue(lexer);

	if(!lexer.next() || !lexer.isStop()){
		throw CompilerException("Every instruction must be closed by a semicolon");
	}

	Declaration* declare = new Declaration(type, variable);

	declare->addLast(value);

	program->addLast(declare);
}

void Parser::parseAssignment(Program* program, string variable) throw (CompilerException){
	ParseNode* value = readValue(lexer);

	if(!lexer.next() || !lexer.isStop()){
		throw CompilerException("Every instruction must be closed by a semicolon");
	}

	Assignment* assign = new Assignment(variable);

	assign->addLast(value);

	program->addLast(assign);
}
<commit_msg>Introduce a system to manage the priority of operators<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include <iostream>
#include <cctype>
#include <list>

#include <commons/Types.h>
#include <commons/Utils.h>

#include "Parser.h"
#include "Operators.h"

using std::string;
using std::ios_base;
using std::list;

Program* Parser::parse() throw (CompilerException) {
	Program* program = new Program();

	while(lexer.next()){
		if(!lexer.isWord()){
			throw CompilerException("An instruction can only start with a call or an assignation");
		}

		string word = lexer.getCurrentToken();

		if(!lexer.next()){
			throw CompilerException("Incomplete instruction");
		}

		if(lexer.isLeftParenth()){ //is a call
			parseCall(program, word);
		} else if(lexer.isWord()){ //is a declaration
			parseDeclaration(program, word);
		} else if(lexer.isAssign()){ //is an assign
			parseAssignment(program, word);
		} else {
			throw CompilerException("Not an instruction");
		}
	}

	return program;
}

ParseNode* readValue(Lexer& lexer);

void Parser::parseCall(Program* program, string call) throw (CompilerException){
	if(call != "Print"){
		throw CompilerException("The call \"" + call + "\" does not exist");
	}

	ParseNode* value = readValue(lexer);

	if(!lexer.next() || !lexer.isRightParenth()){
		throw CompilerException("The call must be closed with a right parenth");
	}

	if(!lexer.next() || !lexer.isStop()){
		throw CompilerException("Every instruction must be closed by a semicolon");
	}

	Print* print = new Print();

	print->addLast(value);

	program->addLast(print);
}

void Parser::parseDeclaration(Program* program, string typeName) throw (CompilerException){
	if(typeName != "int" && typeName != "string"){
		throw CompilerException("Invalid type");
	}

	Type type;
	if(typeName == "int"){
		type = INT;
	} else {
		type = STRING;
	}

	string variable = lexer.getCurrentToken();

	if(!lexer.next() || !lexer.isAssign()){
		throw CompilerException("A variable declaration must followed by '='");
	}

	ParseNode* value = readValue(lexer);

	if(!lexer.next() || !lexer.isStop()){
		throw CompilerException("Every instruction must be closed by a semicolon");
	}

	Declaration* declare = new Declaration(type, variable);

	declare->addLast(value);

	program->addLast(declare);
}

void Parser::parseAssignment(Program* program, string variable) throw (CompilerException){
	ParseNode* value = readValue(lexer);

	if(!lexer.next() || !lexer.isStop()){
		throw CompilerException("Every instruction must be closed by a semicolon");
	}

	Assignment* assign = new Assignment(variable);

	assign->addLast(value);

	program->addLast(assign);
}

enum Operator {
	ADD, MUL, SUB, DIV, ERROR
};

class Part {
	public:
		virtual bool isResolved() = 0;
		virtual Operator getOperator() { return ERROR; }
		virtual Value* getValue(){ return NULL; }
};

class Resolved : public Part {
	public:
		Resolved(Value* v) : value(v) {}
		bool isResolved() { return true; }
		Value* getValue() { return value; }

	private:
		Value* value;
};

class Unresolved : public Part {
	public:
		Unresolved(Operator o) : op(o) {}
		bool isResolved() { return false; }
		Operator getOperator() { return op; }

	private:
		Operator op;
};

int priority(Operator op){
	switch(op){
		case MUL:
		case DIV:
			return 10;
		case ADD:
		case SUB:
			return 0;
		default:
			return -1; //TOOD should never happen
	}
}

ParseNode* readValue(Lexer& lexer){
	list<Part*> parts;

	while(true){
		if(!lexer.next()){
			throw CompilerException("Waiting for a value");
		}

		Value* node = NULL;

		if(lexer.isLitteral()){
			string litteral = lexer.getCurrentToken();

			node = new Litteral(litteral);
		} else if(lexer.isWord()){
			string variableRight = lexer.getCurrentToken();

			node = new VariableValue(variableRight);
		} else if(lexer.isInteger()){
			string integer = lexer.getCurrentToken();
			int value = toNumber<int>(integer);

			node = new Integer(value);
		} else {
			throw CompilerException("Invalid value");
		}

		parts.push_back(new Resolved(node));

		if(!lexer.next()){
			break;
		}

		if(lexer.isAddition()){
			parts.push_back(new Unresolved(ADD));
		} else if(lexer.isSubtraction()){
			parts.push_back(new Unresolved(SUB));
		} else {
			lexer.pushBack();
			break;
		}
	}

	while(parts.size() > 3){
		int i = 0;
		int debug = 0;
		int maxPriority = -1;
		list<Part*>::iterator it, end, max;
		for(it = parts.begin(), end = parts.end(); it != end; ++it){
			Part* part = *it;

			if(!part->isResolved()){
				if(priority(part->getOperator()) > maxPriority){
					maxPriority = priority(part->getOperator());
					max = it;
					i = debug;
				}
			}

			debug++;
		}

		list<Part*>::iterator first = max;
		--first;

		Part* left = *first;
		Part* center = *max;

		++max;
		Part* right = *max;

		Value* lhs = left->getValue();
		Operator op = center->getOperator();
		Value* rhs = right->getValue();

		Value* value = NULL;

		if(op == ADD){
			value = new Addition();
		} else if(op == SUB){
			value = new Subtraction();
		}

		value->addLast(lhs);
		value->addLast(rhs);

		parts.erase(first, ++max);
		parts.insert(max, new Resolved(value));
	}

	Value* value;

	if(parts.size() == 1){
		value = (*parts.begin())->getValue();
	} else {
		list<Part*>::iterator it = parts.begin();

		Value* lhs = (*it++)->getValue();
		Operator op = (*it++)->getOperator();
		Value* rhs = (*it++)->getValue();

		if(op == ADD){
			value = new Addition();
		} else if(op == SUB){
			value = new Subtraction();
		}

		value->addLast(lhs);
		value->addLast(rhs);
	}

	parts.clear();

	return value;
}

<|endoftext|>


<commit_before>
/** \file text_user_session.cpp
 *
 * \brief Contains source code relating to textual (console based)
 * user interface with Phatbooks application.
 *
 * \author Matthew Harvey
 * \date 04 July 2012.
 *
 * Copyright (c) 2012, Matthew Harvey. All rights reserved.
 */

#include "text_user_session.hpp"
#include "phatbooks_database_connection.hpp"
#include <boost/bind.hpp>
#include <cassert>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

using boost::bind;
using std::cin;
using std::cout;
using std::endl;
using std::ostringstream;
using std::runtime_error;
using std::string;
using std::vector;

namespace phatbooks
{

void TextUserSession::say_hello()
{
	cout << "Hello!" << endl;
	return;
}

void TextUserSession::print_numbers()
{
	for (int i = 0; i != 5; ++i)
	{
		cout << i << '\t';
	}
	cout << endl;
	return;
}

void TextUserSession::quit()
{
	cout << "Exiting application..." << endl;
	return;
}

TextUserSession::TextUserSession():
	m_dummy_menu(new Menu),
	m_database_connection(new PhatbooksDatabaseConnection)
{
#warning unimplemented function body
	// Set up all the Menu objects.
	m_dummy_menu->add_item
	(	"Say hello",
		bind(&TextUserSession::say_hello, this)
	);
	m_dummy_menu->add_item
	(	"Print some numbers",
		bind(&TextUserSession::print_numbers, this)
	);
	m_dummy_menu->add_item
	(	"Quit",
		bind(&TextUserSession::quit, this),
		false,
		"x"
	);
}

TextUserSession::~TextUserSession()
{
}

void
TextUserSession::run()
{
	cout << endl << "Welcome to Phatbooks." << endl << endl;

#warning unimplemented function body

	// Get filename from user.
	// ...

	// Open connection with file.
	// ...

	// Setup file.
	// ...

	// Present the first menu.
	// ...
	m_dummy_menu->present_to_user();

	// Farewell the user.
	// ...

	return;
}

void
TextUserSession::Menu::add_item
(	string const& p_name,
	CallbackType p_callback,
	bool p_repeat_menu,
	string const& p_special_label
)
{
	MenuItem item(p_name, p_callback, p_repeat_menu, p_special_label);
	for
	(	ItemContainer::const_iterator it = m_items.begin();
		it != m_items.end();
		++it
	)
	{
		if (item.name() == it->name())
		{
			throw runtime_error("MenuItem with name already in Menu.");
		}
	}
	m_items.push_back(item);
	return;
}

void
TextUserSession::Menu::present_to_user()
{
	bool replay_menu = false;
	do
	{
		// Determine how to label each menu item
		int item_number = 1;
		string::size_type max_label_length = 0;
		vector<string> label_vec;
		for
		(	ItemContainer::const_iterator it = m_items.begin();
			it != m_items.end();
			++it
		)
		{
			string label;
			if (it->has_special_label())
			{
				label = it->special_label();
			}
			else
			{
				ostringstream oss;
				oss << item_number;
				label = oss.str();
				++item_number;
			}
			if (label.size() > max_label_length)
			{
				max_label_length = label.size();
			}
			label_vec.push_back(label);
		}

		// Print the menu
		ItemContainer::const_iterator items_iter = m_items.begin();
		for (vector<string>::size_type i = 0; i != label_vec.size(); ++i)
		{
			assert (i != m_items.size());
			assert (items_iter != m_items.end());
			cout << label_vec[i]
				 << string(max_label_length + 1 - label_vec[i].size(), ' ')
				 << items_iter->name()
				 << endl;
			++items_iter;
		}
		cout << endl << "Enter an option from the above menu: ";

		// Get user input
		bool invocation_successful = false;
		string input;
		do
		{
			bool input_successful = getline(cin, input);
			if (input_successful)
			{
				// Find if input corresponds to an item label
				ItemContainer::iterator items_iter2 = m_items.begin();
				for (vector<string>::size_type i = 0; i != label_vec.size(); ++i)
				{
					assert (items_iter2 != m_items.end());
					if (input == label_vec[i])
					{
						// User has selected one of the items.
						items_iter2->invoke();
						replay_menu = items_iter2->repeat_menu();
						invocation_successful = true;
						break;
					}
					else
					{
						++items_iter2;
					}
				}
				if (!invocation_successful)
				{
					cout << "Your input does not match any of the available "
					     << "options. Please try again."
						 << endl
						 << "Enter an option from the above menu: ";
				}
			}
			else
			{
				// There was an error receiving input
				assert (!cin);
				cin.clear();
				assert (cin);
				cout << "There has been an error receiving your input. "
					 << "Please try again: " << endl;
			}
		}
		while (!invocation_successful);
	}
	while (replay_menu);

	return;
}

TextUserSession::Menu::MenuItem::MenuItem
(	string const& p_name,
	Menu::CallbackType p_callback,
	bool p_repeat_menu,
	string const& p_special_label
):
	m_name(string()),
	m_callback(p_callback),
	m_repeat_menu(p_repeat_menu),
	m_special_label(p_special_label)
{
	if (p_name.empty())
	{
		throw runtime_error("p_name is empty.");
	}
	assert (p_name.size() > 0);
	m_name = p_name;
}

string
TextUserSession::Menu::MenuItem::name() const
{
	return m_name;
}

string
TextUserSession::Menu::MenuItem::special_label() const
{
	if (m_special_label.empty())
	{
		throw runtime_error("Item does not have special label.");
	}
	assert (!m_special_label.empty());
	return m_special_label;
}

bool
TextUserSession::Menu::MenuItem::repeat_menu() const
{
	return m_repeat_menu;
}

bool
TextUserSession::Menu::MenuItem::has_special_label() const
{
	return !m_special_label.empty();
}

void
TextUserSession::Menu::MenuItem::invoke()
{
	return m_callback();
}

bool
TextUserSession::Menu::MenuItem::operator<(MenuItem const& rhs) const
{
	return this->m_name < rhs.m_name;
}

}  // namespace phatbooks

<commit_msg>Tidied implementation of TextUserSession::Menu::present_to_user.<commit_after>
/** \file text_user_session.cpp
 *
 * \brief Contains source code relating to textual (console based)
 * user interface with Phatbooks application.
 *
 * \author Matthew Harvey
 * \date 04 July 2012.
 *
 * Copyright (c) 2012, Matthew Harvey. All rights reserved.
 */

#include "text_user_session.hpp"
#include "phatbooks_database_connection.hpp"
#include <boost/bind.hpp>
#include <algorithm>
#include <cassert>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

using boost::bind;
using std::cin;
using std::cout;
using std::endl;
using std::max;
using std::ostringstream;
using std::runtime_error;
using std::string;
using std::vector;

namespace phatbooks
{

void TextUserSession::say_hello()
{
	cout << "Hello!" << endl;
	return;
}

void TextUserSession::print_numbers()
{
	for (int i = 0; i != 5; ++i)
	{
		cout << i << '\t';
	}
	cout << endl;
	return;
}

void TextUserSession::quit()
{
	cout << "Exiting application..." << endl;
	return;
}

TextUserSession::TextUserSession():
	m_dummy_menu(new Menu),
	m_database_connection(new PhatbooksDatabaseConnection)
{
#warning unimplemented function body
	// Set up all the Menu objects.
	m_dummy_menu->add_item
	(	"Say hello",
		bind(&TextUserSession::say_hello, this)
	);
	m_dummy_menu->add_item
	(	"Print some numbers",
		bind(&TextUserSession::print_numbers, this)
	);
	m_dummy_menu->add_item
	(	"Quit",
		bind(&TextUserSession::quit, this),
		false,
		"x"
	);
}

TextUserSession::~TextUserSession()
{
}

void
TextUserSession::run()
{
	cout << endl << "Welcome to Phatbooks." << endl << endl;

#warning unimplemented function body

	// Get filename from user.
	// ...

	// Open connection with file.
	// ...

	// Setup file.
	// ...

	// Present the first menu.
	// ...
	m_dummy_menu->present_to_user();

	// Farewell the user.
	// ...

	return;
}

void
TextUserSession::Menu::add_item
(	string const& p_name,
	CallbackType p_callback,
	bool p_repeat_menu,
	string const& p_special_label
)
{
	MenuItem item(p_name, p_callback, p_repeat_menu, p_special_label);
	for
	(	ItemContainer::const_iterator it = m_items.begin();
		it != m_items.end();
		++it
	)
	{
		if (item.name() == it->name())
		{
			throw runtime_error("MenuItem with name already in Menu.");
		}
	}
	m_items.push_back(item);
	return;
}

void
TextUserSession::Menu::present_to_user()
{
	typedef vector<string>::size_type vec_sz;
	bool replay_menu = false;

	do
	{
		// Determine how to label each menu item
		int item_num = 1;
		string::size_type max_label_length = 0;
		vector<string> label_vec;
		ItemContainer::iterator it;
		for(it = m_items.begin(); it != m_items.end(); ++it)
		{
			if (it->has_special_label())
			{
				label_vec.push_back(it->special_label());
			}
			else
			{
				ostringstream oss;
				oss << item_num++;
				label_vec.push_back(oss.str());
			}
			max_label_length = max(label_vec.back().size(), max_label_length);
		}

		// Print the menu
		it = m_items.begin();
		cout << endl;
		for (vec_sz i = 0; i != label_vec.size(); ++i, ++it)
		{
			assert (it != m_items.end());
			cout << label_vec[i]
				 << string(max_label_length + 1 - label_vec[i].size(), ' ')
				 << it->name() << endl;
		}
		cout << endl << "Enter an option from the above menu: ";

		// Get user input
		bool invocation_successful = false;
		string input;
		do
		{
			while (!getline(cin, input))
			{
				cin.clear();
				cout << "There has been an error receiving your input."
				     << "Please try again: ";
			}

			// See whether input corresponds to any of the item labels.
			// This crude linear search is not optimal but it's simple,
			// and is fast enough for all except ridiculously large
			// user menus.
			it = m_items.begin();
			for
			(	vec_sz i = 0;
				i != label_vec.size() && !invocation_successful;
				++i, ++it
			)
			{
				assert (it != m_items.end());
				if (input == label_vec[i])
				{
					// User has selected one of the items.
					it->invoke();
					replay_menu = it->repeat_menu();
					invocation_successful = true;
				}
			}
			if (!invocation_successful)
			{
				cout << "Your input does not match any of the available "
					 << "options. Please try again." << endl
					 << "Enter an option from the above menu: ";
			}
		}
		while (!invocation_successful);
	}
	while (replay_menu);

	return;
}

TextUserSession::Menu::MenuItem::MenuItem
(	string const& p_name,
	Menu::CallbackType p_callback,
	bool p_repeat_menu,
	string const& p_special_label
):
	m_name(string()),
	m_callback(p_callback),
	m_repeat_menu(p_repeat_menu),
	m_special_label(p_special_label)
{
	if (p_name.empty())
	{
		throw runtime_error("p_name is empty.");
	}
	assert (p_name.size() > 0);
	m_name = p_name;
}

string
TextUserSession::Menu::MenuItem::name() const
{
	return m_name;
}

string
TextUserSession::Menu::MenuItem::special_label() const
{
	if (m_special_label.empty())
	{
		throw runtime_error("Item does not have special label.");
	}
	assert (!m_special_label.empty());
	return m_special_label;
}

bool
TextUserSession::Menu::MenuItem::repeat_menu() const
{
	return m_repeat_menu;
}

bool
TextUserSession::Menu::MenuItem::has_special_label() const
{
	return !m_special_label.empty();
}

void
TextUserSession::Menu::MenuItem::invoke()
{
	return m_callback();
}

bool
TextUserSession::Menu::MenuItem::operator<(MenuItem const& rhs) const
{
	return this->m_name < rhs.m_name;
}

}  // namespace phatbooks

<|endoftext|>


<commit_before>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Globals, compile-time constants and runconfig abstractions.
  */

#include "thcrap.h"

json_t* global_cfg = NULL;

const char* PROJECT_NAME(void)
{
	return "Touhou Community Reliant Automatic Patcher";
}
const char* PROJECT_NAME_SHORT(void)
{
	return "thcrap";
}
const char* PROJECT_URL(void)
{
	return "https://www.thpatch.net/wiki/Touhou_Patch_Center:Download";
}
DWORD PROJECT_VERSION(void)
{
	return 0x20201023;
}
const char* PROJECT_VERSION_STRING(void)
{
	static char ver_str[11] = {0};
	if(!ver_str[0]) {
		str_hexdate_format(ver_str, PROJECT_VERSION());
	}
	return ver_str;
}
const char* PROJECT_BRANCH(void)
{
	return "stable";
}

void globalconfig_init(void)
{
	json_decref(global_cfg);
	global_cfg = json_load_file_report("config/config.js");
	if (!global_cfg) {
		global_cfg = json_object();
	}
}

int globalconfig_dump(void)
{
	return json_dump_file(global_cfg, "config/config.js", JSON_INDENT(2) | JSON_SORT_KEYS);
}

BOOL globalconfig_get_boolean(char* key, const BOOL default_value)
{
	if (!global_cfg) {
		globalconfig_init();
	}
	errno = 0;
	json_t* value_json = json_object_get(global_cfg, key);
	if (!value_json) {
		errno = ENOENT;
		return default_value;
	}
	return json_boolean_value(value_json);
}

int globalconfig_set_boolean(char* key, const BOOL value)
{
	if (!global_cfg) {
		globalconfig_init();
	}
	json_t* j_value = json_boolean(value);
	if (json_equal(j_value, json_object_get(global_cfg, key))) {
		json_decref(j_value);
		return 0;
	}
	json_object_set_new(global_cfg, key, j_value);
	return globalconfig_dump();
}

long long globalconfig_get_integer(char* key, const long long default_value)
{
	if (!global_cfg) {
		globalconfig_init();
	}
	errno = 0;
	json_t* value_json = json_object_get(global_cfg, key);
	if (!value_json) {
		errno = ENOENT;
		return default_value;
	}
	return json_integer_value(value_json);
}

int globalconfig_set_integer(char* key, const long long value)
{
	if (!global_cfg) {
		globalconfig_init();
	}
	json_t* j_value = json_integer(value);
	if (json_equal(j_value, json_object_get(global_cfg, key))) {
		json_decref(j_value);
		return 0;
	}
	json_object_set_new(global_cfg, key, j_value);
	return globalconfig_dump();
}

void globalconfig_release(void)
{
	json_decref(global_cfg);
	global_cfg = json_incref(NULL);
}

void* __cdecl thcrap_alloc(size_t size) {
	return malloc(size);
}

void __cdecl thcrap_free(void *mem) {
	free(mem);
}
<commit_msg>Update version number<commit_after>/**
  * Touhou Community Reliant Automatic Patcher
  * Main DLL
  *
  * ----
  *
  * Globals, compile-time constants and runconfig abstractions.
  */

#include "thcrap.h"

json_t* global_cfg = NULL;

const char* PROJECT_NAME(void)
{
	return "Touhou Community Reliant Automatic Patcher";
}
const char* PROJECT_NAME_SHORT(void)
{
	return "thcrap";
}
const char* PROJECT_URL(void)
{
	return "https://www.thpatch.net/wiki/Touhou_Patch_Center:Download";
}
DWORD PROJECT_VERSION(void)
{
	return 0x20201104;
}
const char* PROJECT_VERSION_STRING(void)
{
	static char ver_str[11] = {0};
	if(!ver_str[0]) {
		str_hexdate_format(ver_str, PROJECT_VERSION());
	}
	return ver_str;
}
const char* PROJECT_BRANCH(void)
{
	return "stable";
}

void globalconfig_init(void)
{
	json_decref(global_cfg);
	global_cfg = json_load_file_report("config/config.js");
	if (!global_cfg) {
		global_cfg = json_object();
	}
}

int globalconfig_dump(void)
{
	return json_dump_file(global_cfg, "config/config.js", JSON_INDENT(2) | JSON_SORT_KEYS);
}

BOOL globalconfig_get_boolean(char* key, const BOOL default_value)
{
	if (!global_cfg) {
		globalconfig_init();
	}
	errno = 0;
	json_t* value_json = json_object_get(global_cfg, key);
	if (!value_json) {
		errno = ENOENT;
		return default_value;
	}
	return json_boolean_value(value_json);
}

int globalconfig_set_boolean(char* key, const BOOL value)
{
	if (!global_cfg) {
		globalconfig_init();
	}
	json_t* j_value = json_boolean(value);
	if (json_equal(j_value, json_object_get(global_cfg, key))) {
		json_decref(j_value);
		return 0;
	}
	json_object_set_new(global_cfg, key, j_value);
	return globalconfig_dump();
}

long long globalconfig_get_integer(char* key, const long long default_value)
{
	if (!global_cfg) {
		globalconfig_init();
	}
	errno = 0;
	json_t* value_json = json_object_get(global_cfg, key);
	if (!value_json) {
		errno = ENOENT;
		return default_value;
	}
	return json_integer_value(value_json);
}

int globalconfig_set_integer(char* key, const long long value)
{
	if (!global_cfg) {
		globalconfig_init();
	}
	json_t* j_value = json_integer(value);
	if (json_equal(j_value, json_object_get(global_cfg, key))) {
		json_decref(j_value);
		return 0;
	}
	json_object_set_new(global_cfg, key, j_value);
	return globalconfig_dump();
}

void globalconfig_release(void)
{
	json_decref(global_cfg);
	global_cfg = json_incref(NULL);
}

void* __cdecl thcrap_alloc(size_t size) {
	return malloc(size);
}

void __cdecl thcrap_free(void *mem) {
	free(mem);
}
<|endoftext|>


<commit_before>
#include <cstdio>
#include <string.h>
#include <strings.h>
#include <stdio.h> // for file output
#include <fstream>
#include <iostream>

#include <boost/version.hpp>

#include "utils/logoutput.h"
#include "utils/polygon.h"
#include "utils/gettime.h"
#include "utils/SVG.h"

#include "VoronoiQuadrilateralization.h"

using arachne::Point;

namespace arachne
{

Polygons generateTestPoly(size_t size, Point border)
{
    Polygons polys;
    PolygonRef poly = polys.newPoly();
    for (int i = 0; i < size; i++)
    {
        poly.emplace_back(rand() % border.X, rand() % border.Y);
    }

    polys = polys.unionPolygons();
//     polys = polys.offset(border.X*1.2, ClipperLib::jtRound);

//     polys = polys.offset(border.X*2, ClipperLib::jtRound);
//     polys = polys.offset(-border.X*1.8, ClipperLib::jtRound);

    polys = polys.offset(-10, ClipperLib::jtRound);
    polys = polys.offset(20, ClipperLib::jtRound);
    polys = polys.offset(-10, ClipperLib::jtRound);
//     polys = polys.offset(-border.X/200, ClipperLib::jtRound);
//     polys = polys.offset(border.X/100, ClipperLib::jtRound);
//     polys = polys.offset(-border.X/200, ClipperLib::jtRound);
    polys = polys.unionPolygons();
    return polys;
}

void test()
{

    // Preparing Input Geometries.
    int r;
    r = 1558617038;
    r = time(0);
//     r = 1558618076;
    r = 1558692831;
    srand(r);
    printf("random seed: %d\n", r);
    logError("boost version: %s\n", BOOST_LIB_VERSION);

    Polygons polys = generateTestPoly(20, Point(10000, 10000));
    {
        SVG svg("output/outline.svg", AABB(Point(0,0), Point(10000, 10000)));
        svg.writePolygons(polys);
    }

    TimeKeeper tk;

    VoronoiQuadrilateralization vq(polys);

    logError("Toal processing took %fs\n", tk.restart());
}

} // namespace arachne

int main() {
    arachne::test();
    return 0;
}
<commit_msg>use simpler test case<commit_after>
#include <cstdio>
#include <string.h>
#include <strings.h>
#include <stdio.h> // for file output
#include <fstream>
#include <iostream>

#include <boost/version.hpp>

#include "utils/logoutput.h"
#include "utils/polygon.h"
#include "utils/gettime.h"
#include "utils/SVG.h"

#include "VoronoiQuadrilateralization.h"

using arachne::Point;

namespace arachne
{

Polygons generateTestPoly(size_t size, Point border)
{
    Polygons polys;
    PolygonRef poly = polys.newPoly();
    for (int i = 0; i < size; i++)
    {
        poly.emplace_back(rand() % border.X, rand() % border.Y);
    }

    polys = polys.unionPolygons();
//     polys = polys.offset(border.X*1.2, ClipperLib::jtRound);

//     polys = polys.offset(border.X*2, ClipperLib::jtRound);
//     polys = polys.offset(-border.X*1.8, ClipperLib::jtRound);

    polys = polys.offset(-10, ClipperLib::jtRound);
    polys = polys.offset(20, ClipperLib::jtRound);
    polys = polys.offset(-10, ClipperLib::jtRound);
//     polys = polys.offset(-border.X/200, ClipperLib::jtRound);
//     polys = polys.offset(border.X/100, ClipperLib::jtRound);
//     polys = polys.offset(-border.X/200, ClipperLib::jtRound);
    polys = polys.unionPolygons();
    return polys;
}

static Polygons test_poly_1;

void generateTestPolys()
{
    PolygonRef poly = test_poly_1.newPoly();
    poly.emplace_back(0, 0);
    poly.emplace_back(10000, 0);
    poly.emplace_back(5000, 1000);
    poly.emplace_back(4000, 2000);
    poly.emplace_back(3000, 5000);
    poly.emplace_back(2000, 6000);
    poly.emplace_back(1000, 5000);
    poly.emplace_back(0, 3000);
    PolygonRef hole = test_poly_1.newPoly();
    hole.emplace_back(500,500);
    hole.emplace_back(600,500);
    hole.emplace_back(650,450);
}

void test()
{

    // Preparing Input Geometries.
    int r;
    r = 1558617038;
    r = time(0);
//     r = 1558618076;
    r = 1558692831;
    srand(r);
    printf("random seed: %d\n", r);
    logError("boost version: %s\n", BOOST_LIB_VERSION);

    generateTestPolys();

//     Polygons polys = generateTestPoly(20, Point(10000, 10000));
    Polygons polys = test_poly_1;
    {
        SVG svg("output/outline.svg", AABB(Point(0,0), Point(10000, 10000)));
        svg.writePolygons(polys);
    }

    TimeKeeper tk;

    VoronoiQuadrilateralization vq(polys);

    logError("Toal processing took %fs\n", tk.restart());
}

} // namespace arachne

int main() {
    arachne::test();
    return 0;
}
<|endoftext|>


<commit_before>#include "AppInfo.h"
#include "SudokuSolver.h"

#include <algorithm>
#include <chrono>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main(int argc, char *argv[])
{
   vector<string> inputPuzzles;

   if (argc > 1) {
      cout << "- " << APPNAME_VERSION << " started\n\n";

      for (int i = 1; i < argc; ++i) {
         inputPuzzles.push_back(argv[i]);
      }

      for (const auto &fileName : inputPuzzles) {
         try {
            ifstream Input(fileName.c_str());

            if (!Input) {
               cerr << "- ERROR:  can not open file " << fileName << "\n\n";
               exit(EXIT_FAILURE);
            }

            cout << "---- Sudoku puzzle file: " << fileName << "\n\n";

            SudokuGrid puzzle;
            vector<SudokuGrid> solutions(5);

            Input >> puzzle;
            cout << "- Number of clues: " << puzzle.getNumberOfCellsSolved()
                 << "\n\n"
                 << puzzle << endl;
            SudokuSolver sdkSolver(puzzle, 15);

            auto startTP = chrono::system_clock::now();
            solutions = sdkSolver.solve();
            chrono::duration<double> dur =
               chrono::system_clock::now() - startTP;

            cout << "---- Processing time: " << fixed << setprecision(4)
                 << dur.count() << " sec\n"
                 << endl;
            cout << "---- Sudoku solution(s), " << solutions.size()
                 << " found:\n"
                 << endl;

            for (const auto &solution : solutions) {
               cout << solution << "\n";
            }
         } catch (const exception &e) {
            clog << "- EXCEPTION " << argv[0] << ": " << e.what() << endl;
         } catch (...) {
            clog << "- UNKNOWN EXCEPTION " << argv[0] << endl;
         }
      }
   }
   else {
      cout << "- USAGE: " << argv[0] << " <Sudoku files>" << endl;
   }

   return 0;
}
<commit_msg>Removed using namespace std;<commit_after>#include "AppInfo.h"
#include "SudokuSolver.h"

#include <algorithm>
#include <chrono>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

int main(int argc, char *argv[])
{
   std::vector<std::string> inputPuzzles;

   if (argc > 1) {
      std::cout << "- " << APPNAME_VERSION << " started\n\n";

      for (int i = 1; i < argc; ++i) {
         inputPuzzles.push_back(argv[i]);
      }

      for (const auto &fileName : inputPuzzles) {
         try {
            std::ifstream Input(fileName.c_str());

            if (!Input) {
               std::cerr << "- ERROR:  can not open file " << fileName
                         << "\n\n";
               exit(EXIT_FAILURE);
            }

            std::cout << "---- Sudoku puzzle file: " << fileName << "\n\n";

            SudokuGrid puzzle;
            std::vector<SudokuGrid> solutions(5);

            Input >> puzzle;
            std::cout << "- Number of clues: "
                      << puzzle.getNumberOfCellsSolved() << "\n\n"
                      << puzzle << std::endl;
            SudokuSolver sdkSolver(puzzle, 15);

            auto startTP = std::chrono::system_clock::now();
            solutions = sdkSolver.solve();
            std::chrono::duration<double> dur =
               std::chrono::system_clock::now() - startTP;

            std::cout << "---- Processing time: " << std::fixed
                      << std::setprecision(4) << dur.count() << " sec\n\n";
            std::cout << "---- Sudoku solution(s), " << solutions.size()
                      << " found:\n"
                      << std::endl;

            for (const auto &solution : solutions) {
               std::cout << solution << "\n";
            }
         } catch (const std::exception &e) {
            std::clog << "- EXCEPTION " << argv[0] << ": " << e.what()
                      << std::endl;
         } catch (...) {
            std::clog << "- UNKNOWN EXCEPTION " << argv[0] << std::endl;
         }
      }
   }
   else {
      std::cout << "- USAGE: " << argv[0] << " <Sudoku files>" << std::endl;
   }

   return 0;
}
<|endoftext|>