<commit_before>#include "wtf/buffer.h"

namespace wtf {

OutputBuffer::OutputBuffer(std::ostream* out) : out_{out} {}

void OutputBuffer::StartChunk(ChunkHeader header, PartHeader* parts,
                              size_t part_count) {
  static constexpr size_t kChunkHeaderSize = 6 * sizeof(uint32_t);
  static constexpr size_t kPartHeaderSize = 3 * sizeof(uint32_t);

  // Compute layout.
  uint32_t chunk_length = kChunkHeaderSize + part_count * kPartHeaderSize;
  uint32_t part_offset = 0;
  for (size_t i = 0; i < part_count; i++) {
    PartHeader* part = &parts[i];
    part->offset = part_offset;

    // Compute aligned length.
    uint32_t aligned_length = part->length;
    uint32_t rem = aligned_length % kAlignment;
    if (rem) {
      aligned_length += kAlignment - rem;
    }

    chunk_length += aligned_length;
    part_offset += aligned_length;
  }

  // Write out chunk header.
  AppendUint32(header.id);
  AppendUint32(header.type);
  AppendUint32(chunk_length);
  AppendUint32(header.start_time);
  AppendUint32(header.end_time);
  AppendUint32(part_count);

  // Write out each part snapshot.
  for (size_t i = 0; i < part_count; i++) {
    PartHeader* part = &parts[i];
    AppendUint32(part->type);
    AppendUint32(part->offset);
    AppendUint32(part->length);
  }
}

StringTable::StringTable() = default;

int StringTable::GetStringId(const std::string& str) {
  if (str.empty()) {
    return kEmptyStringId;
  }

  platform::lock_guard<platform::mutex> lock{mu_};
  auto it = strings_to_id_.find(str);
  if (it == strings_to_id_.end()) {
    // New string.
    int id = strings_.size();
    strings_.push_back(str);
    strings_to_id_[str] = id;
    return id;
  } else {
    return it->second;
  }
}

void StringTable::PopulateHeader(OutputBuffer::PartHeader* header) {
  platform::lock_guard<platform::mutex> lock{mu_};

  // Compute size.
  size_t raw_length = 0;
  for (const auto& s : strings_) {
    raw_length += s.size() + 1;
  }

  header->type = 0x30000;
  header->offset = 0;
  header->length = raw_length;
}

bool StringTable::WriteTo(OutputBuffer::PartHeader* header,
                          OutputBuffer* output_buffer) {
  platform::lock_guard<platform::mutex> lock{mu_};

  // Output up to the previously noted size.
  size_t raw_length = 0;
  size_t expected_raw_length = header->length;
  for (const auto& s : strings_) {
    raw_length += s.size() + 1;
    if (raw_length <= expected_raw_length) {
      output_buffer->Append(s.c_str(), s.size() + 1);  // Write null term.
      if (raw_length == expected_raw_length) {
        // Clean end.
        break;
      }
    } else {
      return false;
    }
  }
  output_buffer->Align();
  return true;
}

void StringTable::Clear() {
  platform::lock_guard<platform::mutex> lock{mu_};
  strings_.clear();
  strings_to_id_.clear();
}

EventBuffer::EventBuffer(size_t chunk_size_bytes) {
  if (chunk_size_bytes < kMinimumChunkSizeBytes) {
    chunk_size_bytes = kMinimumChunkSizeBytes;
  }
  chunk_limit_ = chunk_size_bytes / sizeof(uint32_t);

  head_ = current_ = new Chunk(chunk_limit_);
}

EventBuffer::~EventBuffer() {
  Chunk* chunk = head_;
  while (chunk) {
    Chunk* next_chunk = chunk->next;
    delete chunk;
    chunk = next_chunk;
  }
}

void EventBuffer::FreezePrefixSlots() {
  Chunk* chunk = current_;
  frozen_prefix_slots_.resize(chunk->size);
  for (size_t i = 0; i < frozen_prefix_slots_.size(); i++) {
    frozen_prefix_slots_[i] = chunk->slots[i];
  }
  chunk->size = 0;
  chunk->published_size = 0;
}

uint32_t* EventBuffer::ExpandAndAddSlots(size_t count) {
  Chunk* new_chunk = new Chunk(chunk_limit_);
  new_chunk->size = count;

  // Publish the final size of the old chunk.
  current_->published_size.store(current_->size,
                                 platform::memory_order_release);

  // Publish that we have a new 'count' sized chunk.
  current_->next.store(new_chunk, platform::memory_order_release);

  // Make new chunk current (does not modify shared state).
  current_ = new_chunk;

  return new_chunk->slots;
}

void EventBuffer::PopulateHeader(OutputBuffer::PartHeader* header) {
  size_t published_slot_count = 0;
  for (Chunk* chunk = head_; chunk;
       chunk = chunk->next.load(platform::memory_order_acquire)) {
    published_slot_count +=
        chunk->published_size.load(platform::memory_order_acquire);
    published_slot_count -= chunk->skip_count;
  }

  header->type = 0x20002;
  header->offset = 0;
  header->length =
      (frozen_prefix_slots().size() + published_slot_count) * sizeof(uint32_t);
}

bool EventBuffer::WriteTo(OutputBuffer::PartHeader* header,
                          OutputBuffer* output_buffer,
                          bool clear_written_data) {
  Chunk* chunk = head_;
  size_t count = header->length / sizeof(uint32_t);

  // Write the frozen prefix.
  if (count < frozen_prefix_slots_.size()) {
    return false;
  }
  count -= frozen_prefix_slots_.size();
  for (uint32_t prefix_value : frozen_prefix_slots_) {
    if (output_buffer) {
      output_buffer->AppendUint32(prefix_value);
    }
  }

  // Write the main part of the buffer chunk by chunk.
  while (count > 0) {
    if (!chunk) {
      // Size mismatch.
      return false;
    }

    // Load the next chunk in the list early. If this is not null, it is
    // absolutely guaranteed that the writer will not make any further
    // updates to this chunk. Switching these loads weakens the guarantee.
    Chunk* next_chunk = chunk->next.load(platform::memory_order_acquire);
    size_t published_size =
        chunk->published_size.load(platform::memory_order_acquire);

    size_t skip_count = chunk->skip_count;
    size_t remaining = published_size - skip_count;
    if (remaining > count) {
      remaining = count;
    }

    // Write the remaining slots.
    for (size_t i = 0; i < remaining; i++) {
      if (output_buffer) {
        output_buffer->AppendUint32(chunk->slots[skip_count + i]);
      }
    }
    count -= remaining;

    // Clear data and reset head if applicable.
    if (clear_written_data) {
      chunk->skip_count += remaining;
      // If the writer is done with this one (next_chunk != nullptr),
      // we are moving on to the next chunk (count > 0), and we are on the
      // head_, then kill it and reset the head.
      if (next_chunk && count > 0 && chunk == head_) {
        // TODO(laurenzo): Put these back into a thread local pool and re-use
        // them.
        delete head_;
        head_ = next_chunk;
      }
    }

    chunk = next_chunk;
  }
  return true;
}

}  // namespace wtf
<commit_msg>Add comment<commit_after>#include "wtf/buffer.h"

namespace wtf {

OutputBuffer::OutputBuffer(std::ostream* out) : out_{out} {}

void OutputBuffer::StartChunk(ChunkHeader header, PartHeader* parts,
                              size_t part_count) {
  static constexpr size_t kChunkHeaderSize = 6 * sizeof(uint32_t);
  static constexpr size_t kPartHeaderSize = 3 * sizeof(uint32_t);

  // Compute layout.
  uint32_t chunk_length = kChunkHeaderSize + part_count * kPartHeaderSize;
  uint32_t part_offset = 0;
  for (size_t i = 0; i < part_count; i++) {
    PartHeader* part = &parts[i];
    part->offset = part_offset;

    // Compute aligned length.
    uint32_t aligned_length = part->length;
    uint32_t rem = aligned_length % kAlignment;
    if (rem) {
      aligned_length += kAlignment - rem;
    }

    chunk_length += aligned_length;
    part_offset += aligned_length;
  }

  // Write out chunk header.
  AppendUint32(header.id);
  AppendUint32(header.type);
  AppendUint32(chunk_length);
  AppendUint32(header.start_time);
  AppendUint32(header.end_time);
  AppendUint32(part_count);

  // Write out each part snapshot.
  for (size_t i = 0; i < part_count; i++) {
    PartHeader* part = &parts[i];
    AppendUint32(part->type);
    AppendUint32(part->offset);
    AppendUint32(part->length);
  }
}

StringTable::StringTable() = default;

int StringTable::GetStringId(const std::string& str) {
  if (str.empty()) {
    return kEmptyStringId;
  }

  platform::lock_guard<platform::mutex> lock{mu_};
  auto it = strings_to_id_.find(str);
  if (it == strings_to_id_.end()) {
    // New string.
    int id = strings_.size();
    strings_.push_back(str);
    strings_to_id_[str] = id;
    return id;
  } else {
    return it->second;
  }
}

void StringTable::PopulateHeader(OutputBuffer::PartHeader* header) {
  platform::lock_guard<platform::mutex> lock{mu_};

  // Compute size.
  size_t raw_length = 0;
  for (const auto& s : strings_) {
    raw_length += s.size() + 1;
  }

  header->type = 0x30000;
  header->offset = 0;
  header->length = raw_length;
}

bool StringTable::WriteTo(OutputBuffer::PartHeader* header,
                          OutputBuffer* output_buffer) {
  platform::lock_guard<platform::mutex> lock{mu_};

  // Output up to the previously noted size.
  size_t raw_length = 0;
  size_t expected_raw_length = header->length;
  for (const auto& s : strings_) {
    raw_length += s.size() + 1;
    if (raw_length <= expected_raw_length) {
      output_buffer->Append(s.c_str(), s.size() + 1);  // Write null term.
      if (raw_length == expected_raw_length) {
        // Clean end.
        break;
      }
    } else {
      return false;
    }
  }
  output_buffer->Align();
  return true;
}

void StringTable::Clear() {
  platform::lock_guard<platform::mutex> lock{mu_};
  strings_.clear();
  strings_to_id_.clear();
}

EventBuffer::EventBuffer(size_t chunk_size_bytes) {
  if (chunk_size_bytes < kMinimumChunkSizeBytes) {
    chunk_size_bytes = kMinimumChunkSizeBytes;
  }
  chunk_limit_ = chunk_size_bytes / sizeof(uint32_t);

  head_ = current_ = new Chunk(chunk_limit_);
}

EventBuffer::~EventBuffer() {
  Chunk* chunk = head_;
  while (chunk) {
    Chunk* next_chunk = chunk->next;
    delete chunk;
    chunk = next_chunk;
  }
}

void EventBuffer::FreezePrefixSlots() {
  Chunk* chunk = current_;
  frozen_prefix_slots_.resize(chunk->size);
  for (size_t i = 0; i < frozen_prefix_slots_.size(); i++) {
    frozen_prefix_slots_[i] = chunk->slots[i];
  }
  chunk->size = 0;
  chunk->published_size = 0;
}

uint32_t* EventBuffer::ExpandAndAddSlots(size_t count) {
  Chunk* new_chunk = new Chunk(chunk_limit_);
  new_chunk->size = count;

  // Publish the final size of the old chunk.
  current_->published_size.store(current_->size,
                                 platform::memory_order_release);

  // Publish that we have a new 'count' sized chunk.
  // This must come after the store to published_size as it signifies that no
  // further updates will be made to published_size.
  current_->next.store(new_chunk, platform::memory_order_release);

  // Make new chunk current (does not modify shared state).
  current_ = new_chunk;

  return new_chunk->slots;
}

void EventBuffer::PopulateHeader(OutputBuffer::PartHeader* header) {
  size_t published_slot_count = 0;
  for (Chunk* chunk = head_; chunk;
       chunk = chunk->next.load(platform::memory_order_acquire)) {
    published_slot_count +=
        chunk->published_size.load(platform::memory_order_acquire);
    published_slot_count -= chunk->skip_count;
  }

  header->type = 0x20002;
  header->offset = 0;
  header->length =
      (frozen_prefix_slots().size() + published_slot_count) * sizeof(uint32_t);
}

bool EventBuffer::WriteTo(OutputBuffer::PartHeader* header,
                          OutputBuffer* output_buffer,
                          bool clear_written_data) {
  Chunk* chunk = head_;
  size_t count = header->length / sizeof(uint32_t);

  // Write the frozen prefix.
  if (count < frozen_prefix_slots_.size()) {
    return false;
  }
  count -= frozen_prefix_slots_.size();
  for (uint32_t prefix_value : frozen_prefix_slots_) {
    if (output_buffer) {
      output_buffer->AppendUint32(prefix_value);
    }
  }

  // Write the main part of the buffer chunk by chunk.
  while (count > 0) {
    if (!chunk) {
      // Size mismatch.
      return false;
    }

    // Load the next chunk in the list early. If this is not null, it is
    // absolutely guaranteed that the writer will not make any further
    // updates to this chunk. Switching these loads weakens the guarantee.
    Chunk* next_chunk = chunk->next.load(platform::memory_order_acquire);
    size_t published_size =
        chunk->published_size.load(platform::memory_order_acquire);

    size_t skip_count = chunk->skip_count;
    size_t remaining = published_size - skip_count;
    if (remaining > count) {
      remaining = count;
    }

    // Write the remaining slots.
    for (size_t i = 0; i < remaining; i++) {
      if (output_buffer) {
        output_buffer->AppendUint32(chunk->slots[skip_count + i]);
      }
    }
    count -= remaining;

    // Clear data and reset head if applicable.
    if (clear_written_data) {
      chunk->skip_count += remaining;
      // If the writer is done with this one (next_chunk != nullptr),
      // we are moving on to the next chunk (count > 0), and we are on the
      // head_, then kill it and reset the head.
      if (next_chunk && count > 0 && chunk == head_) {
        // TODO(laurenzo): Put these back into a thread local pool and re-use
        // them.
        delete head_;
        head_ = next_chunk;
      }
    }

    chunk = next_chunk;
  }
  return true;
}

}  // namespace wtf
<|endoftext|>


<commit_before>//
// SqratImport: Supports importing of squirrel modules
//

//
// Copyright (c) 2009 Brandon Jones
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//  1. The origin of this software must not be misrepresented; you must not
//  claim that you wrote the original software. If you use this software
//  in a product, an acknowledgment in the product documentation would be
//  appreciated but is not required.
//
//  2. Altered source versions must be plainly marked as such, and must not be
//  misrepresented as being the original software.
//
//  3. This notice may not be removed or altered from any source
//  distribution.
//

#include "sqimport.h"
#include "sqmodule.h"

//#include "sqratlib/sqratBase.h"
#include <sqstdio.h>
#include <string>

#if defined(_WIN32)

#include <windows.h>

#elif defined(__unix)

#include <dlfcn.h>

#endif

typedef SQRESULT (*SQMODULELOAD)(HSQUIRRELVM v, HSQAPI sq);

static HSQAPI sqapi = NULL;

// Create and populate the HSQAPI structure with function pointers
// If new functions are added to the Squirrel API, they should be added here too
static HSQAPI sqrat_newapi() {
    HSQAPI sq = (HSQAPI)sq_malloc(sizeof(sq_api));

    /*vm*/
    sq->open = sq_open;
    sq->newthread = sq_newthread;
    sq->seterrorhandler = sq_seterrorhandler;
    sq->close = sq_close;
    sq->setforeignptr = sq_setforeignptr;
    sq->getforeignptr = sq_getforeignptr;
    sq->setprintfunc = sq_setprintfunc;
    sq->getprintfunc = sq_getprintfunc;
    sq->suspendvm = sq_suspendvm;
    sq->wakeupvm = sq_wakeupvm;
    sq->getvmstate = sq_getvmstate;

    /*compiler*/
    sq->compile = sq_compile;
    sq->compilebuffer = sq_compilebuffer;
    sq->enabledebuginfo = sq_enabledebuginfo;
    sq->notifyallexceptions = sq_notifyallexceptions;
    sq->setcompilererrorhandler = sq_setcompilererrorhandler;

    /*stack operations*/
    sq->push = sq_push;
    sq->pop = sq_pop;
    sq->poptop = sq_poptop;
    sq->remove = sq_remove;
    sq->gettop = sq_gettop;
    sq->settop = sq_settop;
    sq->reservestack = sq_reservestack;
    sq->cmp = sq_cmp;
    sq->move = sq_move;

    /*object creation handling*/
    sq->newuserdata = sq_newuserdata;
    sq->newtable = sq_newtable;
    sq->newarray = sq_newarray;
    sq->newclosure = sq_newclosure;
    sq->setparamscheck = sq_setparamscheck;
    sq->bindenv = sq_bindenv;
    sq->pushstring = sq_pushstring;
    sq->pushfloat = sq_pushfloat;
    sq->pushinteger = sq_pushinteger;
    sq->pushbool = sq_pushbool;
    sq->pushuserpointer = sq_pushuserpointer;
    sq->pushnull = sq_pushnull;
    sq->gettype = sq_gettype;
    sq->getsize = sq_getsize;
    sq->getbase = sq_getbase;
    sq->instanceof = sq_instanceof;
    sq->tostring = sq_tostring;
    sq->tobool = sq_tobool;
    sq->getstring = sq_getstring;
    sq->getinteger = sq_getinteger;
    sq->getthread = sq_getthread;
    sq->getbool = sq_getbool;
    sq->getuserpointer = sq_getuserpointer;
    sq->getuserdata = sq_getuserdata;
    sq->settypetag = sq_settypetag;
    sq->gettypetag = sq_gettypetag;
    sq->setreleasehook = sq_setreleasehook;
    sq->getscratchpad = sq_getscratchpad;
    sq->getclosureinfo = sq_getclosureinfo;
    sq->setnativeclosurename = sq_setnativeclosurename;
    sq->setinstanceup = sq_setinstanceup;
    sq->getinstanceup = sq_getinstanceup;
    sq->setclassudsize = sq_setclassudsize;
    sq->newclass = sq_newclass;
    sq->createinstance = sq_createinstance;
    sq->setattributes = sq_setattributes;
    sq->getattributes = sq_getattributes;
    sq->getclass = sq_getclass;
    sq->weakref = sq_weakref;
    sq->getdefaultdelegate = sq_getdefaultdelegate;

    /*object manipulation*/
    sq->pushroottable = sq_pushroottable;
    sq->pushregistrytable = sq_pushregistrytable;
    sq->pushconsttable = sq_pushconsttable;
    sq->setroottable = sq_setroottable;
    sq->setconsttable = sq_setconsttable;
    sq->newslot = sq_newslot;
    sq->deleteslot = sq_deleteslot;
    sq->set = sq_set;
    sq->get = sq_get;
    sq->rawset = sq_rawset;
    sq->rawget = sq_rawget;
    sq->rawdeleteslot = sq_rawdeleteslot;
    sq->arrayappend = sq_arrayappend;
    sq->arraypop = sq_arraypop;
    sq->arrayresize = sq_arrayresize;
    sq->arrayreverse = sq_arrayreverse;
    sq->arrayremove = sq_arrayremove;
    sq->arrayinsert = sq_arrayinsert;
    sq->setdelegate = sq_setdelegate;
    sq->getdelegate = sq_getdelegate;
    sq->clone = sq_clone;
    sq->setfreevariable = sq_setfreevariable;
    sq->next = sq_next;
    sq->getweakrefval = sq_getweakrefval;
    sq->clear = sq_clear;

    /*calls*/
    sq->call = sq_call;
    sq->resume = sq_resume;
    sq->getlocal = sq_getlocal;
    sq->getfreevariable = sq_getfreevariable;
    sq->throwerror = sq_throwerror;
    sq->reseterror = sq_reseterror;
    sq->getlasterror = sq_getlasterror;

    /*raw object handling*/
    sq->getstackobj = sq_getstackobj;
    sq->pushobject = sq_pushobject;
    sq->addref = sq_addref;
    sq->release = sq_release;
    sq->resetobject = sq_resetobject;
    sq->objtostring = sq_objtostring;
    sq->objtobool = sq_objtobool;
    sq->objtointeger = sq_objtointeger;
    sq->objtofloat = sq_objtofloat;
    sq->getobjtypetag = sq_getobjtypetag;

    /*GC*/
    sq->collectgarbage = sq_collectgarbage;

    /*serialization*/
    sq->writeclosure = sq_writeclosure;
    sq->readclosure = sq_readclosure;

    /*mem allocation*/
    sq->malloc = sq_malloc;
    sq->realloc = sq_realloc;
    sq->free = sq_free;

    /*debug*/
    sq->stackinfos = sq_stackinfos;
    sq->setdebughook = sq_setdebughook;

    return sq;
}

static SQRESULT sqrat_importscript(HSQUIRRELVM v, const SQChar* moduleName) {
    std::basic_string<SQChar> filename(moduleName);
    filename += _SC(".nut");
    if(SQ_FAILED(sqstd_loadfile(v, moduleName, true))) {
        if(SQ_FAILED(sqstd_loadfile(v, filename.c_str(), true))) {
            return SQ_ERROR;
        }
    }
    sq_push(v, -2);
    sq_call(v, 1, false, true);
    return SQ_OK;
}

static SQRESULT sqrat_importbin(HSQUIRRELVM v, const SQChar* moduleName) {
#ifdef SQUNICODE
#warning sqrat_importbin() Not Implemented
    return SQ_ERROR;
#else
    SQMODULELOAD modLoad = 0;

#if defined(_WIN32)
    HMODULE mod;
    mod = GetModuleHandle(moduleName);
    if(mod == NULL) {
        mod = LoadLibrary(moduleName);
        if(mod == NULL) {
            return SQ_ERROR;
        }
    }

    modLoad = (SQMODULELOAD)GetProcAddress(mod, "sqmodule_load");
    if(modLoad == NULL) {
        FreeLibrary(mod);
        return SQ_ERROR;
    }
#elif defined(__unix)
    /* adding .so to moduleName? */
    void *mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD); //RTLD_NOLOAD flag is not specified in POSIX.1-2001..so not the best solution :(
    if (mod == NULL) {
        mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL);
        if (mod == NULL)
            return SQ_ERROR;
    }
    modLoad = (SQMODULELOAD) dlsym(mod, "sqmodule_load");
    if (modLoad == NULL) {
        dlclose(mod);
        return SQ_ERROR;
    }
#endif

    if(sqapi == NULL) {
        sqapi = sqrat_newapi(); // Caching this for multiple imports is probably a very good idea
    }

    SQRESULT res = modLoad(v, sqapi);

    return res;
#endif
}

SQRESULT sqrat_import(HSQUIRRELVM v) {
    const SQChar* moduleName;
    HSQOBJECT table;
    SQRESULT res = SQ_OK;

    sq_getstring(v, -2, &moduleName);
    sq_getstackobj(v, -1, &table);
    sq_addref(v, &table);

    sq_settop(v, 0); // Clear Stack
    sq_pushobject(v, table); // Push the target table onto the stack

    if(SQ_FAILED(sqrat_importscript(v, moduleName))) {
        res = sqrat_importbin(v, moduleName);
    }

    sq_settop(v, 0); // Clean up the stack (just in case the module load leaves it messy)
    sq_pushobject(v, table); // return the target table
    sq_release(v, &table);

    return res;
}

static SQInteger sqratbase_import(HSQUIRRELVM v) {
    SQInteger args = sq_gettop(v);
    switch(args) {
    case 2:
        sq_pushroottable(v);
        break;
    case 3:
        // should already have the desired table pushed onto the stack
        break;
    default:
        // Error, unexpected number of arguments
        break;
    }

    sqrat_import(v);

    return 1;
}

SQRESULT sqrat_register_importlib(HSQUIRRELVM v) {
    sq_pushroottable(v);

    sq_pushstring(v, _SC("import"), -1);
    sq_newclosure(v, &sqratbase_import, 0);
    sq_newslot(v, -3, 0);

    sq_pop(v, 1); // pop sqrat table

    return SQ_OK;
}
<commit_msg>Rework logic to find module file:<commit_after>//
// SqratImport: Supports importing of squirrel modules
//

//
// Copyright (c) 2009 Brandon Jones
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
//  1. The origin of this software must not be misrepresented; you must not
//  claim that you wrote the original software. If you use this software
//  in a product, an acknowledgment in the product documentation would be
//  appreciated but is not required.
//
//  2. Altered source versions must be plainly marked as such, and must not be
//  misrepresented as being the original software.
//
//  3. This notice may not be removed or altered from any source
//  distribution.
//

#include "sqimport.h"
#include "sqmodule.h"

//#include "sqratlib/sqratBase.h"
#include <sqstdio.h>
#include <string>
// getenv
#include <stdlib.h>

#if defined(_WIN32)

#include <windows.h>

#elif defined(__unix)

#include <dlfcn.h>

#endif

typedef SQRESULT (*SQMODULELOAD)(HSQUIRRELVM v, HSQAPI sq);

static HSQAPI sqapi = NULL;

// Create and populate the HSQAPI structure with function pointers
// If new functions are added to the Squirrel API, they should be added here too
static HSQAPI sqrat_newapi() {
    HSQAPI sq = (HSQAPI)sq_malloc(sizeof(sq_api));

    /*vm*/
    sq->open = sq_open;
    sq->newthread = sq_newthread;
    sq->seterrorhandler = sq_seterrorhandler;
    sq->close = sq_close;
    sq->setforeignptr = sq_setforeignptr;
    sq->getforeignptr = sq_getforeignptr;
    sq->setprintfunc = sq_setprintfunc;
    sq->getprintfunc = sq_getprintfunc;
    sq->suspendvm = sq_suspendvm;
    sq->wakeupvm = sq_wakeupvm;
    sq->getvmstate = sq_getvmstate;

    /*compiler*/
    sq->compile = sq_compile;
    sq->compilebuffer = sq_compilebuffer;
    sq->enabledebuginfo = sq_enabledebuginfo;
    sq->notifyallexceptions = sq_notifyallexceptions;
    sq->setcompilererrorhandler = sq_setcompilererrorhandler;

    /*stack operations*/
    sq->push = sq_push;
    sq->pop = sq_pop;
    sq->poptop = sq_poptop;
    sq->remove = sq_remove;
    sq->gettop = sq_gettop;
    sq->settop = sq_settop;
    sq->reservestack = sq_reservestack;
    sq->cmp = sq_cmp;
    sq->move = sq_move;

    /*object creation handling*/
    sq->newuserdata = sq_newuserdata;
    sq->newtable = sq_newtable;
    sq->newarray = sq_newarray;
    sq->newclosure = sq_newclosure;
    sq->setparamscheck = sq_setparamscheck;
    sq->bindenv = sq_bindenv;
    sq->pushstring = sq_pushstring;
    sq->pushfloat = sq_pushfloat;
    sq->pushinteger = sq_pushinteger;
    sq->pushbool = sq_pushbool;
    sq->pushuserpointer = sq_pushuserpointer;
    sq->pushnull = sq_pushnull;
    sq->gettype = sq_gettype;
    sq->getsize = sq_getsize;
    sq->getbase = sq_getbase;
    sq->instanceof = sq_instanceof;
    sq->tostring = sq_tostring;
    sq->tobool = sq_tobool;
    sq->getstring = sq_getstring;
    sq->getinteger = sq_getinteger;
    sq->getthread = sq_getthread;
    sq->getbool = sq_getbool;
    sq->getuserpointer = sq_getuserpointer;
    sq->getuserdata = sq_getuserdata;
    sq->settypetag = sq_settypetag;
    sq->gettypetag = sq_gettypetag;
    sq->setreleasehook = sq_setreleasehook;
    sq->getscratchpad = sq_getscratchpad;
    sq->getclosureinfo = sq_getclosureinfo;
    sq->setnativeclosurename = sq_setnativeclosurename;
    sq->setinstanceup = sq_setinstanceup;
    sq->getinstanceup = sq_getinstanceup;
    sq->setclassudsize = sq_setclassudsize;
    sq->newclass = sq_newclass;
    sq->createinstance = sq_createinstance;
    sq->setattributes = sq_setattributes;
    sq->getattributes = sq_getattributes;
    sq->getclass = sq_getclass;
    sq->weakref = sq_weakref;
    sq->getdefaultdelegate = sq_getdefaultdelegate;

    /*object manipulation*/
    sq->pushroottable = sq_pushroottable;
    sq->pushregistrytable = sq_pushregistrytable;
    sq->pushconsttable = sq_pushconsttable;
    sq->setroottable = sq_setroottable;
    sq->setconsttable = sq_setconsttable;
    sq->newslot = sq_newslot;
    sq->deleteslot = sq_deleteslot;
    sq->set = sq_set;
    sq->get = sq_get;
    sq->rawset = sq_rawset;
    sq->rawget = sq_rawget;
    sq->rawdeleteslot = sq_rawdeleteslot;
    sq->arrayappend = sq_arrayappend;
    sq->arraypop = sq_arraypop;
    sq->arrayresize = sq_arrayresize;
    sq->arrayreverse = sq_arrayreverse;
    sq->arrayremove = sq_arrayremove;
    sq->arrayinsert = sq_arrayinsert;
    sq->setdelegate = sq_setdelegate;
    sq->getdelegate = sq_getdelegate;
    sq->clone = sq_clone;
    sq->setfreevariable = sq_setfreevariable;
    sq->next = sq_next;
    sq->getweakrefval = sq_getweakrefval;
    sq->clear = sq_clear;

    /*calls*/
    sq->call = sq_call;
    sq->resume = sq_resume;
    sq->getlocal = sq_getlocal;
    sq->getfreevariable = sq_getfreevariable;
    sq->throwerror = sq_throwerror;
    sq->reseterror = sq_reseterror;
    sq->getlasterror = sq_getlasterror;

    /*raw object handling*/
    sq->getstackobj = sq_getstackobj;
    sq->pushobject = sq_pushobject;
    sq->addref = sq_addref;
    sq->release = sq_release;
    sq->resetobject = sq_resetobject;
    sq->objtostring = sq_objtostring;
    sq->objtobool = sq_objtobool;
    sq->objtointeger = sq_objtointeger;
    sq->objtofloat = sq_objtofloat;
    sq->getobjtypetag = sq_getobjtypetag;

    /*GC*/
    sq->collectgarbage = sq_collectgarbage;

    /*serialization*/
    sq->writeclosure = sq_writeclosure;
    sq->readclosure = sq_readclosure;

    /*mem allocation*/
    sq->malloc = sq_malloc;
    sq->realloc = sq_realloc;
    sq->free = sq_free;

    /*debug*/
    sq->stackinfos = sq_stackinfos;
    sq->setdebughook = sq_setdebughook;

    return sq;
}

static SQRESULT sqrat_importscript(HSQUIRRELVM v, const SQChar* filename) {
    if(SQ_FAILED(sqstd_loadfile(v, filename, true))) {
        return SQ_ERROR;
    }
    sq_push(v, -2);
    sq_call(v, 1, false, true);
    return SQ_OK;
}

static SQRESULT sqrat_importbin(HSQUIRRELVM v, const SQChar* moduleName) {
#ifdef SQUNICODE
#warning sqrat_importbin() Not Implemented
    return SQ_ERROR;
#else
    SQMODULELOAD modLoad = 0;

#if defined(_WIN32)
    HMODULE mod;
    mod = GetModuleHandle(moduleName);
    if(mod == NULL) {
        mod = LoadLibrary(moduleName);
        if(mod == NULL) {
            return SQ_ERROR;
        }
    }

    modLoad = (SQMODULELOAD)GetProcAddress(mod, "sqmodule_load");
    if(modLoad == NULL) {
        FreeLibrary(mod);
        return SQ_ERROR;
    }
#elif defined(__unix)
    /* adding .so to moduleName? */
    void *mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD); //RTLD_NOLOAD flag is not specified in POSIX.1-2001..so not the best solution :(
    if (mod == NULL) {
        mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL);
        if (mod == NULL)
            return SQ_ERROR;
    }
    modLoad = (SQMODULELOAD) dlsym(mod, "sqmodule_load");
    if (modLoad == NULL) {
        dlclose(mod);
        return SQ_ERROR;
    }
#endif

    if(sqapi == NULL) {
        sqapi = sqrat_newapi(); // Caching this for multiple imports is probably a very good idea
    }

    SQRESULT res = modLoad(v, sqapi);

    return res;
#endif
}

bool file_exists(const SQChar* filename)
{
    return access(filename, F_OK) == 0;
}

#define NOT_FOUND 100

SQRESULT try_import_path(HSQUIRRELVM v, std::basic_string<SQChar>& fname)
{
    // Try to import module at given path. This tries
    // different module types in order.

    // Check binary module
    fname[fname.size() - 1] = 'd';
    if (file_exists(fname.c_str()))
        return sqrat_importbin(v, fname.c_str());
    // Check bytecode module
    fname[fname.size() - 1] = 'c';
    if (file_exists(fname.c_str()))
        return sqrat_importscript(v, fname.c_str());
    // Check source module
    fname[fname.size() - 1] = 't';
    if (file_exists(fname.c_str()))
        return sqrat_importscript(v, fname.c_str());

    return NOT_FOUND;
}

SQRESULT sqrat_import(HSQUIRRELVM v) {
    const SQChar* moduleName;
    HSQOBJECT table;
    SQRESULT res = SQ_OK;

    sq_getstring(v, -2, &moduleName);
    sq_getstackobj(v, -1, &table);
    sq_addref(v, &table);

    sq_settop(v, 0); // Clear Stack
    sq_pushobject(v, table); // Push the target table onto the stack

    std::basic_string<SQChar> fname;
    // Explicit path is needed for dlopen() later, and won't hurt
    // for other cases
    fname = "./";
    fname += moduleName;
    fname += ".nut";
    res = try_import_path(v, fname);
    if (res == NOT_FOUND) {
        const char *path = getenv("SQPATH");
        if (path)
            fname = path;
        else {
            path = getenv("HOME");
            if (path) {
                fname = path;
                fname += "/.squirrel/lib";
            } else {
                fname = "/usr/lib/squirrel";
            }
        }
        fname += "/";
        fname += moduleName;
        fname += ".nut";
        res = try_import_path(v, fname);
        if (res == NOT_FOUND)
            res = SQ_ERROR;
    }

    sq_settop(v, 0); // Clean up the stack (just in case the module load leaves it messy)
    sq_pushobject(v, table); // return the target table
    sq_release(v, &table);

    return res;
}

static SQInteger sqratbase_import(HSQUIRRELVM v) {
    SQInteger args = sq_gettop(v);
    switch(args) {
    case 2:
        sq_pushroottable(v);
        break;
    case 3:
        // should already have the desired table pushed onto the stack
        break;
    default:
        // Error, unexpected number of arguments
        break;
    }

    sqrat_import(v);

    return 1;
}

SQRESULT sqrat_register_importlib(HSQUIRRELVM v) {
    sq_pushroottable(v);

    sq_pushstring(v, _SC("import"), -1);
    sq_newclosure(v, &sqratbase_import, 0);
    sq_newslot(v, -3, 0);

    sq_pop(v, 1); // pop sqrat table

    return SQ_OK;
}
<|endoftext|>


<commit_before><commit_msg>FsDiscoverer: Remove trailing whitespace<commit_after><|endoftext|>


<commit_before><commit_msg>Fixing the gcc bug <5.0<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2012 Matthew McCormick
 *
 * Licensed 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.
 * */

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <unistd.h> // sleep

float cpu_percentage( unsigned int cpu_usage_delay )
{
	std::string stat_line;
	size_t line_start_pos;
	size_t line_end_pos;
	unsigned long long current_user;
	unsigned long long current_system;
	unsigned long long current_nice;
	unsigned long long current_idle;
	unsigned long long next_user;
	unsigned long long next_system;
	unsigned long long next_nice;
	unsigned long long next_idle;
	unsigned long long diff_user;
	unsigned long long diff_system;
	unsigned long long diff_nice;
	unsigned long long diff_idle;
	std::istringstream iss;

	std::ifstream stat_file("/proc/stat");
	std::getline(stat_file, stat_line);
	stat_file.close();

	// skip "cpu"
	line_start_pos = stat_line.find_first_not_of(" ", 3);
	line_end_pos = stat_line.find_first_of(' ', line_start_pos);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);

	iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
	iss >> current_user >> current_nice >> current_system >> current_idle;
	iss.clear();

	usleep( cpu_usage_delay );

	stat_file.open("/proc/stat");
	std::getline(stat_file, stat_line);
	stat_file.close();

	// skip "cpu"
	line_start_pos = stat_line.find_first_not_of(" ", 3);
	line_end_pos = stat_line.find_first_of(' ', line_start_pos);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);

	iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
	iss >> next_user >> next_nice >> next_system >> next_idle;
	iss.clear();

	diff_user   = next_user - current_user;
	diff_system = next_system - current_system;
	diff_nice   = next_nice - current_nice;
	diff_idle   = next_idle - current_idle;

	return static_cast<float>(diff_user + diff_system + diff_nice)/static_cast<float>(diff_user + diff_system + diff_nice + diff_idle)*100.0;
}

std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines )
{
	std::string meter( graph_lines + 2, ' ' );
	meter[0] = '[';
	meter[meter.length() - 1] = ']';
	int meter_count = 0;
	float percentage;
	std::ostringstream oss;
	oss.precision( 1 );
	oss.setf( std::ios::fixed | std::ios::right );

	percentage = cpu_percentage( cpu_usage_delay );
	float meter_step = 99.9 / graph_lines;
	meter_count = 1;
	while(meter_count*meter_step < percentage)
	{
		meter[meter_count] = '|';
		meter_count++;
	}

	oss << meter;
	oss.width( 5 );
	oss << percentage;
	oss << "%";

	return oss.str();
}

std::string mem_string()
{
	unsigned int total_mem;
	unsigned int used_mem;
	unsigned int unused_mem;
	size_t line_start_pos;
	size_t line_end_pos;
	std::istringstream iss;
	std::ostringstream oss;
	std::string mem_line;

	std::ifstream meminfo_file( "/proc/meminfo" );
	std::getline( meminfo_file, mem_line );
	line_start_pos = mem_line.find_first_of( ':' );
	line_start_pos++;
	line_end_pos = mem_line.find_first_of( 'k' );
	iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
	iss >> total_mem;

	used_mem = total_mem;

	for( unsigned int i = 0; i < 3; i++ )
	{
		std::getline( meminfo_file, mem_line );
		line_start_pos = mem_line.find_first_of( ':' );
		line_start_pos++;
		line_end_pos = mem_line.find_first_of( 'k' );
		iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
		iss >> unused_mem;
		used_mem -= unused_mem;
	}
	meminfo_file.close();

	oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB";

	return oss.str();
}

std::string load_string()
{
	std::ifstream loadavg_file( "/proc/loadavg" );
	std::string load_line;
	std::getline( loadavg_file, load_line );
	loadavg_file.close();

	return load_line.substr( 0, 14 );
}

int main(int argc, char** argv)
{
	unsigned int cpu_usage_delay = 900000;
	unsigned int graph_lines = 10;
	try
	{
		std::istringstream iss;
		iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
		if( argc > 1 )
		{
			iss.str( argv[1] );
			unsigned int status_interval;
			iss >> status_interval;
			cpu_usage_delay = status_interval * 1000000 - 100000;
		}

		if( argc > 2 )
		{
			iss.str( argv[2] );
			iss.clear();
			iss >> graph_lines;
		}
	}
	catch(const std::exception &e)
	{
		std::cerr << "Usage: " << argv[0] << " [tmux_status-interval(seconds)] [graph lines]" << std::endl;
		return 1;
	}

	std::cout << mem_string() << ' ' << cpu_string( cpu_usage_delay, graph_lines ) << ' ' << load_string();

	return 0;
}

<commit_msg>Mac OS X support and BSD function stubs<commit_after>/*
 * Copyright 2012 Matthew McCormick
 *
 * Licensed 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.
 * */

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <unistd.h> // sleep
#include <math.h> // for floorf

// Apple specific.
#if defined(__APPLE__) && defined(__MACH__)
// Mach kernel includes for getting memory and CPU statistics
# include <mach/vm_statistics.h>
# include <mach/processor_info.h>
# include <mach/mach_types.h>
# include <mach/mach_init.h>
# include <mach/mach_host.h>
# include <mach/host_info.h>
# include <mach/mach_error.h>
# include <mach/vm_map.h>
# include <mach/mach.h>
# include <sys/sysctl.h> // for sysctl
# include <sys/types.h> // for integer types
#endif

// if we are on a BSD system
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
// TODO: Includes and *BSD support
# define BSD_BASED 1
#endif

// Function declarations for global use.
float cpu_percentage( unsigned int cpu_usage_delay );
std::string mem_string();
std::string load_string();

// This function is platform independent and therefore can be placed at the top
std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines )
{
	std::string meter( graph_lines + 2, ' ' );
	meter[0] = '[';
	meter[meter.length() - 1] = ']';
	int meter_count = 0;
	float percentage;
	std::ostringstream oss;
	oss.precision( 1 );
	oss.setf( std::ios::fixed | std::ios::right );

	percentage = cpu_percentage( cpu_usage_delay );
	float meter_step = 99.9 / graph_lines;
	meter_count = 1;
	while(meter_count*meter_step < percentage)
	{
		meter[meter_count] = '|';
		meter_count++;
	}

	oss << meter;
	oss.width( 5 );
	oss << percentage;
	oss << "%";

	return oss.str();
}

#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__))
// OSX or BSD based system, use BSD APIs instead

#if defined(__APPLE__) && defined(__MACH__)
std::string mem_string()
{
	// These values are in bytes
	int64_t total_mem;
	int64_t used_mem;
	int64_t unused_mem;
	// blah
	vm_size_t page_size;
	mach_port_t mach_port;
	mach_msg_type_number_t count;
	vm_statistics_data_t vm_stats;
	std::ostringstream oss;

	// Get total physical memory
	int mib[2];
	mib[0] = CTL_HW;
	mib[1] = HW_MEMSIZE;
	size_t length = sizeof(int64_t);
	sysctl(mib, 2, &total_mem, &length, NULL, 0);

	mach_port = mach_host_self();
	count = sizeof(vm_stats) / sizeof(natural_t);
	if (KERN_SUCCESS == host_page_size(mach_port, &page_size) &&
		KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count))
	{
		unused_mem = (int64_t)vm_stats.free_count * (int64_t)page_size;

		used_mem = ((int64_t)vm_stats.active_count +
		(int64_t)vm_stats.inactive_count +
		(int64_t)vm_stats.wire_count) *  (int64_t)page_size;
	}

	oss << used_mem / 1024 / 1024 << '/' << total_mem / 1024 / 1024 << "MB";

	return oss.str();
}

// See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h
// and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/
host_cpu_load_info_data_t _get_cpu_percentage()
{
	kern_return_t		error;
	mach_msg_type_number_t	count;
	host_cpu_load_info_data_t	r_load;
	mach_port_t		mach_port;

	count = HOST_CPU_LOAD_INFO_COUNT;
	mach_port = mach_host_self();
	error = host_statistics(mach_port, HOST_CPU_LOAD_INFO, (host_info_t)&r_load, &count);
	if (error != KERN_SUCCESS)
		return host_cpu_load_info_data_t();

	return r_load;
}

float cpu_percentage( unsigned int cpu_usage_delay )
{
	// Get the load times from the XNU kernel
	host_cpu_load_info_data_t load1 = _get_cpu_percentage();
	usleep(cpu_usage_delay);
	host_cpu_load_info_data_t load2 = _get_cpu_percentage();

	// Current load times
	unsigned long long current_user    = load1.cpu_ticks[CPU_STATE_USER];
	unsigned long long current_system  = load1.cpu_ticks[CPU_STATE_SYSTEM];
	unsigned long long current_nice    = load1.cpu_ticks[CPU_STATE_NICE];
	unsigned long long current_idle    = load1.cpu_ticks[CPU_STATE_IDLE];
	// Next load times
	unsigned long long next_user       = load2.cpu_ticks[CPU_STATE_USER];
	unsigned long long next_system     = load2.cpu_ticks[CPU_STATE_SYSTEM];
	unsigned long long next_nice       = load2.cpu_ticks[CPU_STATE_NICE];
	unsigned long long next_idle       = load2.cpu_ticks[CPU_STATE_IDLE];
	// Difference between the two
	unsigned long long diff_user       = next_user - current_user;
	unsigned long long diff_system     = next_system - current_system;
	unsigned long long diff_nice       = next_nice - current_nice;
	unsigned long long diff_idle       = next_idle - current_idle;

	return static_cast<float>(diff_user + diff_system + diff_nice)/static_cast<float>(diff_user + diff_system + diff_nice + diff_idle)*100.0;
}

#else // APPLE

// BSD type systems (FreeBSD/NetBSD/OpenBSD)
// Incomplete
float cpu_percentage( unsigned int cpu_usage_delay )
{
	return 0.0f;
}

std::string mem_string()
{
	return "0/0 MB";
}

#endif // APPLE

// Both apple and BSD style systems have these api calls
std::string load_string()
{
	std::stringstream ss;
	// Only get 3 load averages
	int nelem = 3;
	double averages[3];
	// based on: http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c
	if(getloadavg(averages, nelem) < 0)
		ss << "0.00 0.00 0.00"; // couldn't get averages.
	else
	{
		for(int i = 0; i < nelem; ++i)
		{
			// Round to nearest, make sure this is only a 0.00 value not a 0.0000
			float avg = floorf(static_cast<float>(averages[i]) * 100 + 0.5) / 100;
			ss << avg << " ";
		}
	}

	return ss.str();
}

#else // APPLE || BSD_BASED

// Linux based system, if it's windows, too much work, they can deal with their compile errors - CMD sucks anyway.
std::string mem_string()
{
	unsigned int total_mem;
	unsigned int used_mem;
	unsigned int unused_mem;
	size_t line_start_pos;
	size_t line_end_pos;
	std::istringstream iss;
	std::ostringstream oss;
	std::string mem_line;

	std::ifstream meminfo_file( "/proc/meminfo" );
	std::getline( meminfo_file, mem_line );
	line_start_pos = mem_line.find_first_of( ':' );
	line_start_pos++;
	line_end_pos = mem_line.find_first_of( 'k' );
	iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
	iss >> total_mem;

	used_mem = total_mem;

	for( unsigned int i = 0; i < 3; i++ )
	{
		std::getline( meminfo_file, mem_line );
		line_start_pos = mem_line.find_first_of( ':' );
		line_start_pos++;
		line_end_pos = mem_line.find_first_of( 'k' );
		iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
		iss >> unused_mem;
		used_mem -= unused_mem;
	}
	meminfo_file.close();

	oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB";

	return oss.str();
}

float cpu_percentage( unsigned int cpu_usage_delay )
{
	std::string stat_line;
	size_t line_start_pos;
	size_t line_end_pos;
	unsigned long long current_user;
	unsigned long long current_system;
	unsigned long long current_nice;
	unsigned long long current_idle;
	unsigned long long next_user;
	unsigned long long next_system;
	unsigned long long next_nice;
	unsigned long long next_idle;
	unsigned long long diff_user;
	unsigned long long diff_system;
	unsigned long long diff_nice;
	unsigned long long diff_idle;
	std::istringstream iss;

	std::ifstream stat_file("/proc/stat");
	std::getline(stat_file, stat_line);
	stat_file.close();

	// skip "cpu"
	line_start_pos = stat_line.find_first_not_of(" ", 3);
	line_end_pos = stat_line.find_first_of(' ', line_start_pos);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);

	iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
	iss >> current_user >> current_nice >> current_system >> current_idle;
	iss.clear();

	usleep( cpu_usage_delay );

	stat_file.open("/proc/stat");
	std::getline(stat_file, stat_line);
	stat_file.close();

	// skip "cpu"
	line_start_pos = stat_line.find_first_not_of(" ", 3);
	line_end_pos = stat_line.find_first_of(' ', line_start_pos);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
	line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);

	iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
	iss >> next_user >> next_nice >> next_system >> next_idle;
	iss.clear();

	diff_user   = next_user - current_user;
	diff_system = next_system - current_system;
	diff_nice   = next_nice - current_nice;
	diff_idle   = next_idle - current_idle;

	return static_cast<float>(diff_user + diff_system + diff_nice)/static_cast<float>(diff_user + diff_system + diff_nice + diff_idle)*100.0;
}

std::string load_string()
{
	std::ifstream loadavg_file( "/proc/loadavg" );
	std::string load_line;
	std::getline( loadavg_file, load_line );
	loadavg_file.close();

	return load_line.substr( 0, 14 );
}

#endif // BSD

int main(int argc, char** argv)
{
	unsigned int cpu_usage_delay = 900000;
	unsigned int graph_lines = 10;
	try
	{
		std::istringstream iss;
		iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
		if( argc > 1 )
		{
			iss.str( argv[1] );
			unsigned int status_interval;
			iss >> status_interval;
			cpu_usage_delay = status_interval * 1000000 - 100000;
		}

		if( argc > 2 )
		{
			iss.str( argv[2] );
			iss.clear();
			iss >> graph_lines;
		}
	}
	catch(const std::exception &e)
	{
		std::cerr << "Usage: " << argv[0] << " [tmux_status-interval(seconds)] [graph lines]" << std::endl;
		return 1;
	}

	std::cout << mem_string() << ' ' << cpu_string( cpu_usage_delay, graph_lines ) << ' ' << load_string();

	return 0;
}

<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////////
//
// BSD 3-Clause License
//
// Copyright (c) 2019, The Regents of the University of California
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

#include "AntennaRepair.h"

#include <cmath>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include <limits>

#include "Net.h"
#include "Pin.h"
#include "grt/GlobalRouter.h"
#include "utl/Logger.h"

namespace grt {

using utl::GRT;

AntennaRepair::AntennaRepair(GlobalRouter* grouter,
                             ant::AntennaChecker* arc,
                             dpl::Opendp* opendp,
                             odb::dbDatabase* db,
                             utl::Logger* logger)
    : _grouter(grouter), _arc(arc), _opendp(opendp), _db(db), _logger(logger)
{
  _block = _db->getChip()->getBlock();
}

int AntennaRepair::checkAntennaViolations(NetRouteMap& routing,
                                          int maxRoutingLayer,
                                          odb::dbMTerm* diodeMTerm)
{
  odb::dbTech* tech = _db->getTech();

  _arc->load_antenna_rules();

  std::map<int, odb::dbTechVia*> defaultVias
      = _grouter->getDefaultVias(maxRoutingLayer);

  for (auto net_route : routing) {
    odb::dbNet* db_net = net_route.first;
    GRoute& route = net_route.second;
    odb::dbWire* wire = odb::dbWire::create(db_net);
    if (wire != nullptr) {
      odb::dbWireEncoder wireEncoder;
      wireEncoder.begin(wire);
      odb::dbWireType wireType = odb::dbWireType::ROUTED;

      for (GSegment& seg : route) {
        if (std::abs(seg.initLayer - seg.finalLayer) > 1) {
          _logger->error(GRT, 68, "Global route segment not valid.");
        }
        int x1 = seg.initX;
        int y1 = seg.initY;
        int x2 = seg.finalX;
        int y2 = seg.finalY;
        int l1 = seg.initLayer;
        int l2 = seg.finalLayer;

        odb::dbTechLayer* currLayer = tech->findRoutingLayer(l1);

        if (l1 == l2) {  // Add wire
          if (x1 == x2 && y1 == y2)
            continue;
          wireEncoder.newPath(currLayer, wireType);
          wireEncoder.addPoint(x1, y1);
          wireEncoder.addPoint(x2, y2);
        } else {  // Add via
          int bottomLayer = (l1 < l2) ? l1 : l2;
          wireEncoder.newPath(currLayer, wireType);
          wireEncoder.addPoint(x1, y1);
          wireEncoder.addTechVia(defaultVias[bottomLayer]);
        }
      }
      wireEncoder.end();

      odb::orderWires(db_net, false, false);

      std::vector<ant::VINFO> netViol = _arc->get_net_antenna_violations(
          db_net,
          diodeMTerm->getMaster()->getConstName(),
          diodeMTerm->getConstName());
      if (!netViol.empty()) {
        _antennaViolations[db_net] = netViol;
        _grouter->addDirtyNet(db_net);
      }

      odb::dbWire::destroy(wire);
    } else {
      _logger->error(GRT, 221, "Cannot create wire for net {}.", db_net->getConstName());
    }
  }

  _logger->info(GRT, 12, "Antenna violations: {}", _antennaViolations.size());
  return _antennaViolations.size();
}

void AntennaRepair::repairAntennas(odb::dbMTerm* diodeMTerm)
{
  int siteWidth = -1;
  int cnt = _diodeInsts.size();
  r_tree fixedInsts;

  auto rows = _block->getRows();
  for (odb::dbRow* db_row : rows) {
    odb::dbSite* site = db_row->getSite();
    int site_width = site->getWidth();
    if (siteWidth == -1) {
      siteWidth = site_width;
    }

    if (siteWidth != site_width) {
      _logger->warn(GRT, 27, "Design has rows with different site widths.");
    }
  }

  deleteFillerCells();

  setInstsPlacementStatus(odb::dbPlacementStatus::FIRM);
  getFixedInstances(fixedInsts);

  for (auto const& violation : _antennaViolations) {
    odb::dbNet* net = violation.first;
    for (int i = 0; i < violation.second.size(); i++) {
      for (odb::dbITerm* sinkITerm : violation.second[i].iterms) {
        odb::dbInst* sinkInst = sinkITerm->getInst();
        for (int j = 0; j < violation.second[i].antenna_cell_nums; j++) {
          std::string antennaInstName = "ANTENNA_" + std::to_string(cnt);
          insertDiode(net,
                      diodeMTerm,
                      sinkInst,
                      sinkITerm,
                      antennaInstName,
                      siteWidth,
                      fixedInsts);
          cnt++;
        }
      }
    }
  }
}

void AntennaRepair::legalizePlacedCells()
{
  AntennaCbk* cbk = new AntennaCbk(_grouter);
  cbk->addOwner(_block);

  _opendp->detailedPlacement(0);
  _opendp->checkPlacement(false);

  cbk->removeOwner();

  // After legalize placement, diodes and violated insts don't need to be FIRM
  setInstsPlacementStatus(odb::dbPlacementStatus::PLACED);
}

void AntennaRepair::deleteFillerCells()
{
  int fillerCnt = 0;
  for (odb::dbInst* inst : _block->getInsts()) {
    if (inst->getMaster()->getType() == odb::dbMasterType::CORE_SPACER) {
      fillerCnt++;
      odb::dbInst::destroy(inst);
    }
  }

  if (fillerCnt > 0) {
    _logger->info(GRT, 11, "Deleted {} filler cells.", fillerCnt);
  }
}

void AntennaRepair::insertDiode(odb::dbNet* net,
                                odb::dbMTerm* diodeMTerm,
                                odb::dbInst* sinkInst,
                                odb::dbITerm* sinkITerm,
                                std::string antennaInstName,
                                int siteWidth,
                                r_tree& fixedInsts)
{
  bool legallyPlaced = false;
  bool placeAtLeft = true;
  int leftOffset = 0;
  int rightOffset = 0;
  int offset;

  std::string netName = net->getConstName();

  odb::dbMaster* antennaMaster = diodeMTerm->getMaster();

  int instLocX, instLocY, instWidth;
  odb::Rect sinkBBox = getInstRect(sinkInst, sinkITerm);
  instLocX = sinkBBox.xMin();
  instLocY = sinkBBox.yMin();
  instWidth = sinkBBox.xMax() - sinkBBox.xMin();
  odb::dbOrientType instOrient = sinkInst->getOrient();

  odb::dbInst* antennaInst
      = odb::dbInst::create(_block, antennaMaster, antennaInstName.c_str());
  odb::dbITerm* antennaITerm
      = antennaInst->findITerm(diodeMTerm->getConstName());
  odb::dbBox* antennaBBox = antennaInst->getBBox();
  int antennaWidth = antennaBBox->xMax() - antennaBBox->xMin();

  odb::Rect coreArea;
  _block->getCoreArea(coreArea);

  // Use R-tree to check if diode will not overlap or cause 1-site spacing with
  // other cells
  int leftPad = _opendp->padGlobalLeft();
  int rightPad = _opendp->padGlobalRight();
  std::vector<value> overlapInsts;
  while (!legallyPlaced) {
    if (placeAtLeft) {
      offset = -(antennaWidth + leftOffset * siteWidth);
      leftOffset++;
      placeAtLeft = false;
    } else {
      offset = instWidth + rightOffset * siteWidth;
      rightOffset++;
      placeAtLeft = true;
    }

    antennaInst->setOrient(instOrient);
    antennaInst->setLocation(instLocX + offset, instLocY);

    odb::dbBox* instBox = antennaInst->getBBox();
    box box(point(instBox->xMin() - ((leftPad + rightPad) * siteWidth) + 1,
                  instBox->yMin() + 1),
            point(instBox->xMax() + ((leftPad + rightPad) * siteWidth) - 1,
                  instBox->yMax() - 1));
    fixedInsts.query(bgi::intersects(box), std::back_inserter(overlapInsts));

    if (overlapInsts.empty() && instBox->xMin() >= coreArea.xMin()
        && instBox->xMax() <= coreArea.xMax()) {
      legallyPlaced = true;
    }
    overlapInsts.clear();
  }

  odb::Rect instRect;
  antennaInst->getBBox()->getBox(instRect);

  // allow detailed placement to move diodes with geometry out of the core area
  // or near macro pins (can be placed out of row)
  if (coreArea.contains(instRect) && !sinkInst->getMaster()->isBlock()) {
    antennaInst->setPlacementStatus(odb::dbPlacementStatus::FIRM);
  } else {
    antennaInst->setPlacementStatus(odb::dbPlacementStatus::PLACED);
  }

  antennaInst->setPlacementStatus(odb::dbPlacementStatus::FIRM);
  odb::dbITerm::connect(antennaITerm, net);
  _diodeInsts.push_back(antennaInst);

  // Add diode to the R-tree of fixed instances
  int fixedInstId = fixedInsts.size();
  box b(point(instRect.xMin(), instRect.yMin()),
        point(instRect.xMax(), instRect.yMax()));
  value v(b, fixedInstId);
  fixedInsts.insert(v);
  fixedInstId++;
}

void AntennaRepair::getFixedInstances(r_tree& fixedInsts)
{
  int fixedInstId = 0;
  for (odb::dbInst* inst : _block->getInsts()) {
    if (inst->getPlacementStatus() == odb::dbPlacementStatus::FIRM) {
      odb::dbBox* instBox = inst->getBBox();
      box b(point(instBox->xMin(), instBox->yMin()),
            point(instBox->xMax(), instBox->yMax()));
      value v(b, fixedInstId);
      fixedInsts.insert(v);
      fixedInstId++;
    }
  }
}

void AntennaRepair::setInstsPlacementStatus(
    odb::dbPlacementStatus placementStatus)
{
  for (auto const& violation : _antennaViolations) {
    for (int i = 0; i < violation.second.size(); i++) {
      for (odb::dbITerm* sinkITerm : violation.second[i].iterms) {
        sinkITerm->getInst()->setPlacementStatus(placementStatus);
      }
    }
  }

  for (odb::dbInst* diodeInst : _diodeInsts) {
    diodeInst->setPlacementStatus(placementStatus);
  }
}

odb::Rect AntennaRepair::getInstRect(odb::dbInst* inst, odb::dbITerm* iterm)
{
  int min = std::numeric_limits<int>::min();
  int max = std::numeric_limits<int>::max();

  int pX, pY;
  inst->getOrigin(pX, pY);
  odb::Point origin = odb::Point(pX, pY);
  odb::dbTransform transform(inst->getOrient(), origin);

  odb::Rect instRect;

  if (inst->getMaster()->isBlock()) {
    instRect = odb::Rect(max, max, min, min);
    odb::dbMTerm* mterm = iterm->getMTerm();
    if (mterm != nullptr) {
      for (odb::dbMPin* mterm_pin : mterm->getMPins()) {
        for (odb::dbBox* mterm_box : mterm_pin->getGeometry()) {
          odb::Rect rect;
          mterm_box->getBox(rect);
          transform.apply(rect);

          instRect = rect;
        }
      }
    }
  } else {
    inst->getBBox()->getBox(instRect);
  }

  return instRect;
}

AntennaCbk::AntennaCbk(GlobalRouter* grouter) : _grouter(grouter)
{
}

void AntennaCbk::inDbPostMoveInst(odb::dbInst* inst)
{
  for (odb::dbITerm* iterm : inst->getITerms()) {
    odb::dbNet* db_net = iterm->getNet();
    if (db_net != nullptr && !db_net->isSpecial())
      _grouter->addDirtyNet(iterm->getNet());
  }
}

}  // namespace grt
<commit_msg>grt: bug fix for diodes inserted near macros<commit_after>/////////////////////////////////////////////////////////////////////////////
//
// BSD 3-Clause License
//
// Copyright (c) 2019, The Regents of the University of California
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

#include "AntennaRepair.h"

#include <cmath>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include <limits>

#include "Net.h"
#include "Pin.h"
#include "grt/GlobalRouter.h"
#include "utl/Logger.h"

namespace grt {

using utl::GRT;

AntennaRepair::AntennaRepair(GlobalRouter* grouter,
                             ant::AntennaChecker* arc,
                             dpl::Opendp* opendp,
                             odb::dbDatabase* db,
                             utl::Logger* logger)
    : _grouter(grouter), _arc(arc), _opendp(opendp), _db(db), _logger(logger)
{
  _block = _db->getChip()->getBlock();
}

int AntennaRepair::checkAntennaViolations(NetRouteMap& routing,
                                          int maxRoutingLayer,
                                          odb::dbMTerm* diodeMTerm)
{
  odb::dbTech* tech = _db->getTech();

  _arc->load_antenna_rules();

  std::map<int, odb::dbTechVia*> defaultVias
      = _grouter->getDefaultVias(maxRoutingLayer);

  for (auto net_route : routing) {
    odb::dbNet* db_net = net_route.first;
    GRoute& route = net_route.second;
    odb::dbWire* wire = odb::dbWire::create(db_net);
    if (wire != nullptr) {
      odb::dbWireEncoder wireEncoder;
      wireEncoder.begin(wire);
      odb::dbWireType wireType = odb::dbWireType::ROUTED;

      for (GSegment& seg : route) {
        if (std::abs(seg.initLayer - seg.finalLayer) > 1) {
          _logger->error(GRT, 68, "Global route segment not valid.");
        }
        int x1 = seg.initX;
        int y1 = seg.initY;
        int x2 = seg.finalX;
        int y2 = seg.finalY;
        int l1 = seg.initLayer;
        int l2 = seg.finalLayer;

        odb::dbTechLayer* currLayer = tech->findRoutingLayer(l1);

        if (l1 == l2) {  // Add wire
          if (x1 == x2 && y1 == y2)
            continue;
          wireEncoder.newPath(currLayer, wireType);
          wireEncoder.addPoint(x1, y1);
          wireEncoder.addPoint(x2, y2);
        } else {  // Add via
          int bottomLayer = (l1 < l2) ? l1 : l2;
          wireEncoder.newPath(currLayer, wireType);
          wireEncoder.addPoint(x1, y1);
          wireEncoder.addTechVia(defaultVias[bottomLayer]);
        }
      }
      wireEncoder.end();

      odb::orderWires(db_net, false, false);

      std::vector<ant::VINFO> netViol = _arc->get_net_antenna_violations(
          db_net,
          diodeMTerm->getMaster()->getConstName(),
          diodeMTerm->getConstName());
      if (!netViol.empty()) {
        _antennaViolations[db_net] = netViol;
        _grouter->addDirtyNet(db_net);
      }

      odb::dbWire::destroy(wire);
    } else {
      _logger->error(GRT, 221, "Cannot create wire for net {}.", db_net->getConstName());
    }
  }

  _logger->info(GRT, 12, "Antenna violations: {}", _antennaViolations.size());
  return _antennaViolations.size();
}

void AntennaRepair::repairAntennas(odb::dbMTerm* diodeMTerm)
{
  int siteWidth = -1;
  int cnt = _diodeInsts.size();
  r_tree fixedInsts;

  auto rows = _block->getRows();
  for (odb::dbRow* db_row : rows) {
    odb::dbSite* site = db_row->getSite();
    int site_width = site->getWidth();
    if (siteWidth == -1) {
      siteWidth = site_width;
    }

    if (siteWidth != site_width) {
      _logger->warn(GRT, 27, "Design has rows with different site widths.");
    }
  }

  deleteFillerCells();

  setInstsPlacementStatus(odb::dbPlacementStatus::FIRM);
  getFixedInstances(fixedInsts);

  for (auto const& violation : _antennaViolations) {
    odb::dbNet* net = violation.first;
    for (int i = 0; i < violation.second.size(); i++) {
      for (odb::dbITerm* sinkITerm : violation.second[i].iterms) {
        odb::dbInst* sinkInst = sinkITerm->getInst();
        for (int j = 0; j < violation.second[i].antenna_cell_nums; j++) {
          std::string antennaInstName = "ANTENNA_" + std::to_string(cnt);
          insertDiode(net,
                      diodeMTerm,
                      sinkInst,
                      sinkITerm,
                      antennaInstName,
                      siteWidth,
                      fixedInsts);
          cnt++;
        }
      }
    }
  }
}

void AntennaRepair::legalizePlacedCells()
{
  AntennaCbk* cbk = new AntennaCbk(_grouter);
  cbk->addOwner(_block);

  _opendp->detailedPlacement(0);
  _opendp->checkPlacement(false);

  cbk->removeOwner();

  // After legalize placement, diodes and violated insts don't need to be FIRM
  setInstsPlacementStatus(odb::dbPlacementStatus::PLACED);
}

void AntennaRepair::deleteFillerCells()
{
  int fillerCnt = 0;
  for (odb::dbInst* inst : _block->getInsts()) {
    if (inst->getMaster()->getType() == odb::dbMasterType::CORE_SPACER) {
      fillerCnt++;
      odb::dbInst::destroy(inst);
    }
  }

  if (fillerCnt > 0) {
    _logger->info(GRT, 11, "Deleted {} filler cells.", fillerCnt);
  }
}

void AntennaRepair::insertDiode(odb::dbNet* net,
                                odb::dbMTerm* diodeMTerm,
                                odb::dbInst* sinkInst,
                                odb::dbITerm* sinkITerm,
                                std::string antennaInstName,
                                int siteWidth,
                                r_tree& fixedInsts)
{
  bool legallyPlaced = false;
  bool placeAtLeft = true;
  int leftOffset = 0;
  int rightOffset = 0;
  int offset;

  std::string netName = net->getConstName();

  odb::dbMaster* antennaMaster = diodeMTerm->getMaster();

  int instLocX, instLocY, instWidth;
  odb::Rect sinkBBox = getInstRect(sinkInst, sinkITerm);
  instLocX = sinkBBox.xMin();
  instLocY = sinkBBox.yMin();
  instWidth = sinkBBox.xMax() - sinkBBox.xMin();
  odb::dbOrientType instOrient = sinkInst->getOrient();

  odb::dbInst* antennaInst
      = odb::dbInst::create(_block, antennaMaster, antennaInstName.c_str());
  odb::dbITerm* antennaITerm
      = antennaInst->findITerm(diodeMTerm->getConstName());
  odb::dbBox* antennaBBox = antennaInst->getBBox();
  int antennaWidth = antennaBBox->xMax() - antennaBBox->xMin();

  odb::Rect coreArea;
  _block->getCoreArea(coreArea);

  // Use R-tree to check if diode will not overlap or cause 1-site spacing with
  // other cells
  int leftPad = _opendp->padGlobalLeft();
  int rightPad = _opendp->padGlobalRight();
  std::vector<value> overlapInsts;
  while (!legallyPlaced) {
    if (placeAtLeft) {
      offset = -(antennaWidth + leftOffset * siteWidth);
      leftOffset++;
      placeAtLeft = false;
    } else {
      offset = instWidth + rightOffset * siteWidth;
      rightOffset++;
      placeAtLeft = true;
    }

    antennaInst->setOrient(instOrient);
    antennaInst->setLocation(instLocX + offset, instLocY);

    odb::dbBox* instBox = antennaInst->getBBox();
    box box(point(instBox->xMin() - ((leftPad + rightPad) * siteWidth) + 1,
                  instBox->yMin() + 1),
            point(instBox->xMax() + ((leftPad + rightPad) * siteWidth) - 1,
                  instBox->yMax() - 1));
    fixedInsts.query(bgi::intersects(box), std::back_inserter(overlapInsts));

    if (overlapInsts.empty() && instBox->xMin() >= coreArea.xMin()
        && instBox->xMax() <= coreArea.xMax()) {
      legallyPlaced = true;
    }
    overlapInsts.clear();
  }

  odb::Rect instRect;
  antennaInst->getBBox()->getBox(instRect);

  // allow detailed placement to move diodes with geometry out of the core area
  // or near macro pins (can be placed out of row)
  if (coreArea.contains(instRect) && !sinkInst->getMaster()->isBlock()) {
    antennaInst->setPlacementStatus(odb::dbPlacementStatus::FIRM);
  } else {
    antennaInst->setPlacementStatus(odb::dbPlacementStatus::PLACED);
  }

  odb::dbITerm::connect(antennaITerm, net);
  _diodeInsts.push_back(antennaInst);

  // Add diode to the R-tree of fixed instances
  int fixedInstId = fixedInsts.size();
  box b(point(instRect.xMin(), instRect.yMin()),
        point(instRect.xMax(), instRect.yMax()));
  value v(b, fixedInstId);
  fixedInsts.insert(v);
  fixedInstId++;
}

void AntennaRepair::getFixedInstances(r_tree& fixedInsts)
{
  int fixedInstId = 0;
  for (odb::dbInst* inst : _block->getInsts()) {
    if (inst->getPlacementStatus() == odb::dbPlacementStatus::FIRM) {
      odb::dbBox* instBox = inst->getBBox();
      box b(point(instBox->xMin(), instBox->yMin()),
            point(instBox->xMax(), instBox->yMax()));
      value v(b, fixedInstId);
      fixedInsts.insert(v);
      fixedInstId++;
    }
  }
}

void AntennaRepair::setInstsPlacementStatus(
    odb::dbPlacementStatus placementStatus)
{
  for (auto const& violation : _antennaViolations) {
    for (int i = 0; i < violation.second.size(); i++) {
      for (odb::dbITerm* sinkITerm : violation.second[i].iterms) {
        if (!sinkITerm->getMTerm()->getMaster()->isBlock()) {
          sinkITerm->getInst()->setPlacementStatus(placementStatus);
        }
      }
    }
  }

  for (odb::dbInst* diodeInst : _diodeInsts) {
    diodeInst->setPlacementStatus(placementStatus);
  }
}

odb::Rect AntennaRepair::getInstRect(odb::dbInst* inst, odb::dbITerm* iterm)
{
  int min = std::numeric_limits<int>::min();
  int max = std::numeric_limits<int>::max();

  int pX, pY;
  inst->getOrigin(pX, pY);
  odb::Point origin = odb::Point(pX, pY);
  odb::dbTransform transform(inst->getOrient(), origin);

  odb::Rect instRect;

  if (inst->getMaster()->isBlock()) {
    instRect = odb::Rect(max, max, min, min);
    odb::dbMTerm* mterm = iterm->getMTerm();
    if (mterm != nullptr) {
      for (odb::dbMPin* mterm_pin : mterm->getMPins()) {
        for (odb::dbBox* mterm_box : mterm_pin->getGeometry()) {
          odb::Rect rect;
          mterm_box->getBox(rect);
          transform.apply(rect);

          instRect = rect;
        }
      }
    }
  } else {
    inst->getBBox()->getBox(instRect);
  }

  return instRect;
}

AntennaCbk::AntennaCbk(GlobalRouter* grouter) : _grouter(grouter)
{
}

void AntennaCbk::inDbPostMoveInst(odb::dbInst* inst)
{
  for (odb::dbITerm* iterm : inst->getITerms()) {
    odb::dbNet* db_net = iterm->getNet();
    if (db_net != nullptr && !db_net->isSpecial())
      _grouter->addDirtyNet(iterm->getNet());
  }
}

}  // namespace grt
<|endoftext|>


<commit_before>#ifndef COUCH_KVSTORE_H
#define COUCH_KVSTORE_H 1

#include "couch_db.h"
#include "kvstore.hh"
#include "item.hh"
#include "stats.hh"
#include "configuration.hh"
#include "mc-kvstore/mc-engine.hh"
#include "tools/cJSON.h"

class EventuallyPersistentEngine;
class EPStats;

typedef union {
    Callback <mutation_result> *setCb;
    Callback <int> *delCb;
} CouchRequestCallback;

#define COUCHSTORE_METADATA_SIZE (2*sizeof(uint32_t) + sizeof(uint64_t))
class CouchRequest {
public:
    CouchRequest(const Item &it, int rev, CouchRequestCallback &cb, bool del);

    uint16_t getVBucketId(void) { return vbucketId; }
    int getRevNum(void) { return fileRevNum; }
    Doc *getDbDoc(void) { return &dbDoc; }
    DocInfo *getDbDocInfo(void) { return &dbDocInfo; }
    Callback<mutation_result> *getSetCallback(void) { return callback.setCb; }
    Callback<int> *getDelCallback(void) { return callback.delCb; }
    int64_t getItemId(void) { return itemId; }
    hrtime_t getDelta() { return (gethrtime() - start) / 1000; }
    size_t getNBytes() { return valuelen; }
    bool   isDelete() { return deleteItem; };

private :
    value_t value;
    size_t valuelen;
    uint8_t meta[COUCHSTORE_METADATA_SIZE];
    uint16_t vbucketId;
    int fileRevNum;
    std::string key;
    Doc dbDoc;
    DocInfo dbDocInfo;
    int64_t itemId;
    bool deleteItem;
    CouchRequestCallback callback;

    hrtime_t start;
};

/**
 * Couchstore kv-store
 */
class CouchKVStore : public KVStore {
public:
    /**
     * Build it!
     */
    CouchKVStore(EventuallyPersistentEngine &theEngine);
    CouchKVStore(const CouchKVStore &from);

    /**
     * Cleanup.
     */
    virtual ~CouchKVStore() {
        close();
    }

    /**
     * Reset database to a clean state.
     */
    void reset(void);

    /**
     * Begin a transaction (if not already in one).
     */
    bool begin(void) {
        intransaction = true;
        return intransaction;
    }

    /**
     * Commit a transaction (unless not currently in one).
     *
     * Returns false if the commit fails.
     */
    bool commit(void);

    /**
     * Rollback a transaction (unless not currently in one).
     */
    void rollback(void) {
        if (intransaction) {
            intransaction = false;
        }
    }

    /**
     * Query the properties of the underlying storage.
     */
    StorageProperties getStorageProperties(void);

    /**
     * Overrides set().
     */
    void set(const Item &item, uint16_t vb_version, Callback<mutation_result> &cb);

    /**
     * Overrides get().
     */
    void get(const std::string &key, uint64_t rowid,
             uint16_t vb, uint16_t vbver, Callback<GetValue> &cb);

    /**
     * Overrides del().
     */
    void del(const Item &itm, uint64_t rowid,
             uint16_t vbver, Callback<int> &cb);

    bool delVBucket(uint16_t vbucket, uint16_t vb_version);

    bool delVBucket(uint16_t vbucket, uint16_t vb_version,
                    std::pair<int64_t, int64_t> row_range);

    vbucket_map_t listPersistedVbuckets(void);

    /**
     * Change the vbucket state in the main DB.
     */
    void vbStateChanged(uint16_t vbucket, vbucket_state_t newState);

    /**
     * Take a snapshot of the stats in the main DB.
     */
    bool snapshotStats(const std::map<std::string, std::string> &m);

     /**
     * Take a snapshot of the vbucket states in the main DB.
     */
    bool snapshotVBuckets(const vbucket_map_t &m);

    /**
     * Overrides dump
     */
    void dump(shared_ptr<Callback<GetValue> > cb);
    void dump(uint16_t vb, shared_ptr<Callback<GetValue> > cb);
    void dumpKeys(const std::vector<uint16_t> &vbids,  shared_ptr<Callback<GetValue> > cb);
    bool isKeyDumpSupported() {
        return true;
    }

    virtual void addStats(const std::string &prefix, ADD_STAT add_stat, const void *c);
    void optimizeWrites(std::vector<queued_item> &items);
    void processTxnSizeChange(size_t txn_size);
    void setVBBatchCount(size_t batch_count);
    void destroyInvalidVBuckets(bool destroyOnlyOne = false) {
        (void) destroyOnlyOne;
    }

    static int recordDbDump(Db* db, DocInfo* docinfo, void *ctx);
    static int recordDbStat(Db* db, DocInfo* docinfo, void *ctx);
    static void readVBState(Db *db, uint16_t vbId, vbucket_state &vbState);

protected:
    void tap(shared_ptr<TapCallback> cb, bool keysOnly,
             std::vector<uint16_t> *vbids);
    bool setVBucketState(uint16_t vbucketId, vbucket_state_t state, uint64_t checkpointId);
    template <typename T>
    void addStat(const std::string &prefix, const char *nm, T val,
                 ADD_STAT add_stat, const void *c);

private:
    EventuallyPersistentEngine &engine;
    EPStats &epStats;
    Configuration &configuration;
    MemcachedEngine *mc;
    std::map<uint16_t, int>dbFileMap;
    std::list<CouchRequest *> pendingReqsQ;
    size_t pendingCommitCnt;
    bool intransaction;

    // stat: the number of docs committed
    uint16_t  docsCommitted;

    // no longer needed, remove once CouchKVStore::addStat is ready
    size_t vbBatchCount;
    size_t vbBatchSize;

    void operator=(const CouchKVStore &from);

    void open();
    void close();
    bool commit2couchstore(void);
    void queue(CouchRequest &req);

    bool getDbFile(uint16_t vbucketId, std::string &dbFileName);
    bool getDbFile(const Item &it, std::string &dbName) {
        return getDbFile(it.getVBucketId(), dbName);
    }

    int checkNewRevNum(std::string &dbname, bool newFile = false);
    int checkNewDbFile(std::string &dbname) {
        return checkNewRevNum(dbname, true);
    }

    void populateFileNameMap(std::vector<std::string> &filenames);
    void getFileNameMap(std::vector<uint16_t> *vbids, std::string &dirname,
                        std::map<uint16_t, int> &filemap);
    void updateDbFileMap(uint16_t vbucketId, int newFileRev,
                        bool insertImmediately = false);
    void remVBucketFromDbFileMap(uint16_t vbucketId);
    couchstore_error_t  openDB(uint16_t vbucketId, uint16_t fileRev, Db **db,
                               uint64_t options, uint16_t *newFileRev = NULL);
    couchstore_error_t saveDocs(uint16_t vbid, int rev, Doc **docs,
                                DocInfo **docinfos, int docCount);
    void commitCallback(CouchRequest **committedReqs, int numReqs, int errCode);
    couchstore_error_t saveVBState(Db *db, vbucket_state &vbState);
    void setDocsCommitted(uint16_t docs);
};

#endif /* COUCHSTORE_KVSTORE_H */
<commit_msg>Use const type for meta data size instead of macro.<commit_after>#ifndef COUCH_KVSTORE_H
#define COUCH_KVSTORE_H 1

#include "couch_db.h"
#include "kvstore.hh"
#include "item.hh"
#include "stats.hh"
#include "configuration.hh"
#include "mc-kvstore/mc-engine.hh"
#include "tools/cJSON.h"

class EventuallyPersistentEngine;
class EPStats;

typedef union {
    Callback <mutation_result> *setCb;
    Callback <int> *delCb;
} CouchRequestCallback;

const size_t COUCHSTORE_METADATA_SIZE (2*sizeof(uint32_t) + sizeof(uint64_t));

class CouchRequest {
public:
    CouchRequest(const Item &it, int rev, CouchRequestCallback &cb, bool del);

    uint16_t getVBucketId(void) { return vbucketId; }
    int getRevNum(void) { return fileRevNum; }
    Doc *getDbDoc(void) { return &dbDoc; }
    DocInfo *getDbDocInfo(void) { return &dbDocInfo; }
    Callback<mutation_result> *getSetCallback(void) { return callback.setCb; }
    Callback<int> *getDelCallback(void) { return callback.delCb; }
    int64_t getItemId(void) { return itemId; }
    hrtime_t getDelta() { return (gethrtime() - start) / 1000; }
    size_t getNBytes() { return valuelen; }
    bool   isDelete() { return deleteItem; };

private :
    value_t value;
    size_t valuelen;
    uint8_t meta[COUCHSTORE_METADATA_SIZE];
    uint16_t vbucketId;
    int fileRevNum;
    std::string key;
    Doc dbDoc;
    DocInfo dbDocInfo;
    int64_t itemId;
    bool deleteItem;
    CouchRequestCallback callback;

    hrtime_t start;
};

/**
 * Couchstore kv-store
 */
class CouchKVStore : public KVStore {
public:
    /**
     * Build it!
     */
    CouchKVStore(EventuallyPersistentEngine &theEngine);
    CouchKVStore(const CouchKVStore &from);

    /**
     * Cleanup.
     */
    virtual ~CouchKVStore() {
        close();
    }

    /**
     * Reset database to a clean state.
     */
    void reset(void);

    /**
     * Begin a transaction (if not already in one).
     */
    bool begin(void) {
        intransaction = true;
        return intransaction;
    }

    /**
     * Commit a transaction (unless not currently in one).
     *
     * Returns false if the commit fails.
     */
    bool commit(void);

    /**
     * Rollback a transaction (unless not currently in one).
     */
    void rollback(void) {
        if (intransaction) {
            intransaction = false;
        }
    }

    /**
     * Query the properties of the underlying storage.
     */
    StorageProperties getStorageProperties(void);

    /**
     * Overrides set().
     */
    void set(const Item &item, uint16_t vb_version, Callback<mutation_result> &cb);

    /**
     * Overrides get().
     */
    void get(const std::string &key, uint64_t rowid,
             uint16_t vb, uint16_t vbver, Callback<GetValue> &cb);

    /**
     * Overrides del().
     */
    void del(const Item &itm, uint64_t rowid,
             uint16_t vbver, Callback<int> &cb);

    bool delVBucket(uint16_t vbucket, uint16_t vb_version);

    bool delVBucket(uint16_t vbucket, uint16_t vb_version,
                    std::pair<int64_t, int64_t> row_range);

    vbucket_map_t listPersistedVbuckets(void);

    /**
     * Change the vbucket state in the main DB.
     */
    void vbStateChanged(uint16_t vbucket, vbucket_state_t newState);

    /**
     * Take a snapshot of the stats in the main DB.
     */
    bool snapshotStats(const std::map<std::string, std::string> &m);

     /**
     * Take a snapshot of the vbucket states in the main DB.
     */
    bool snapshotVBuckets(const vbucket_map_t &m);

    /**
     * Overrides dump
     */
    void dump(shared_ptr<Callback<GetValue> > cb);
    void dump(uint16_t vb, shared_ptr<Callback<GetValue> > cb);
    void dumpKeys(const std::vector<uint16_t> &vbids,  shared_ptr<Callback<GetValue> > cb);
    bool isKeyDumpSupported() {
        return true;
    }

    virtual void addStats(const std::string &prefix, ADD_STAT add_stat, const void *c);
    void optimizeWrites(std::vector<queued_item> &items);
    void processTxnSizeChange(size_t txn_size);
    void setVBBatchCount(size_t batch_count);
    void destroyInvalidVBuckets(bool destroyOnlyOne = false) {
        (void) destroyOnlyOne;
    }

    static int recordDbDump(Db* db, DocInfo* docinfo, void *ctx);
    static int recordDbStat(Db* db, DocInfo* docinfo, void *ctx);
    static void readVBState(Db *db, uint16_t vbId, vbucket_state &vbState);

protected:
    void tap(shared_ptr<TapCallback> cb, bool keysOnly,
             std::vector<uint16_t> *vbids);
    bool setVBucketState(uint16_t vbucketId, vbucket_state_t state, uint64_t checkpointId);
    template <typename T>
    void addStat(const std::string &prefix, const char *nm, T val,
                 ADD_STAT add_stat, const void *c);

private:
    EventuallyPersistentEngine &engine;
    EPStats &epStats;
    Configuration &configuration;
    MemcachedEngine *mc;
    std::map<uint16_t, int>dbFileMap;
    std::list<CouchRequest *> pendingReqsQ;
    size_t pendingCommitCnt;
    bool intransaction;

    // stat: the number of docs committed
    uint16_t  docsCommitted;

    // no longer needed, remove once CouchKVStore::addStat is ready
    size_t vbBatchCount;
    size_t vbBatchSize;

    void operator=(const CouchKVStore &from);

    void open();
    void close();
    bool commit2couchstore(void);
    void queue(CouchRequest &req);

    bool getDbFile(uint16_t vbucketId, std::string &dbFileName);
    bool getDbFile(const Item &it, std::string &dbName) {
        return getDbFile(it.getVBucketId(), dbName);
    }

    int checkNewRevNum(std::string &dbname, bool newFile = false);
    int checkNewDbFile(std::string &dbname) {
        return checkNewRevNum(dbname, true);
    }

    void populateFileNameMap(std::vector<std::string> &filenames);
    void getFileNameMap(std::vector<uint16_t> *vbids, std::string &dirname,
                        std::map<uint16_t, int> &filemap);
    void updateDbFileMap(uint16_t vbucketId, int newFileRev,
                        bool insertImmediately = false);
    void remVBucketFromDbFileMap(uint16_t vbucketId);
    couchstore_error_t  openDB(uint16_t vbucketId, uint16_t fileRev, Db **db,
                               uint64_t options, uint16_t *newFileRev = NULL);
    couchstore_error_t saveDocs(uint16_t vbid, int rev, Doc **docs,
                                DocInfo **docinfos, int docCount);
    void commitCallback(CouchRequest **committedReqs, int numReqs, int errCode);
    couchstore_error_t saveVBState(Db *db, vbucket_state &vbState);
    void setDocsCommitted(uint16_t docs);
};

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


<commit_before>/*
 * Copyright 2011 Esrille Inc.
 *
 * Licensed 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.
 */

#include "HTTPRequest.h"

#include <iostream>
#include <string>

#include "utf.h"

#include "url/URI.h"
#include "http/HTTPCache.h"
#include "http/HTTPConnection.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

int HttpRequest::getContentDescriptor()
{
    return fdContent;  // TODO: call dup internally?
}

std::FILE* HttpRequest::openFile()
{
    if (fdContent == -1)
        return 0;
    std::FILE* file = fdopen(dup(fdContent), "rb");
    if (!file)
        return 0;
    rewind(file);
    return file;
}

std::fstream& HttpRequest::getContent()
{
    if (content.is_open())
        return content;

    char filename[] = "/tmp/esXXXXXX";
    fdContent = mkstemp(filename);
    if (fdContent == -1)
        return content;
    content.open(filename, std::ios_base::trunc | std::ios_base::in | std::ios_base::out | std::ios::binary);
    remove(filename);

    return content;
}

void HttpRequest::notify(bool error)
{
    readyState = DONE;
    errorFlag = error;
    if (!cache)
        return;
    cache->notify(this, error);

    if (handler)
        handler();
}

void HttpRequest::open(const std::u16string& method, const std::u16string& urlString)
{
    URL url(base, urlString);
    request.open(utfconv(method), url);
    readyState = OPENED;
}

void HttpRequest::setRequestHeader(const std::u16string& header, const std::u16string& value)
{
    request.setHeader(utfconv(header), utfconv(value));
}

void HttpRequest::constructResponseFromCache()
{
    readyState = DONE;
    errorFlag = false;
    response.update(cache->getResponseMessage());

    // TODO: deal with partial...
    int fd = cache->getContentDescriptor();
    if (0 <= fd)
        fdContent = dup(fd);

    if (handler)
        handler();
}

void HttpRequest::send()
{
    if (request.getURL().isEmpty()) {
        abort();
        return;
    }
    cache = HttpCacheManager::getInstance().send(this);
    if (!cache || cache->isBusy())
        return;
    constructResponseFromCache();
}

void HttpRequest::abort()
{
    // TODO: implement more details.
    clearHanndler();
    if (cache)
        cache->abort(this);
    else {
        HttpConnectionManager& manager = HttpConnectionManager::getInstance();
        manager.abort(this);
    }
    readyState = UNSENT;
    errorFlag = false;
    request.clear();
    response.clear();
    if (content.is_open())
        content.close();
    if (0 <= fdContent) {
        close(fdContent);
        fdContent = -1;
    }
}

unsigned short HttpRequest::getStatus() const
{
    return response.getStatus();
}

const std::string& HttpRequest::getStatusText() const
{
    return response.getStatusText();
}

const std::string HttpRequest::getResponseHeader(std::u16string header) const
{
    return response.getResponseHeader(utfconv(header));
}

const std::string& HttpRequest::getAllResponseHeaders() const
{
    return response.getAllResponseHeaders();
}

HttpRequest::HttpRequest(const std::u16string& base) :
    base(base),
    readyState(UNSENT),
    errorFlag(false),
    fdContent(-1),
    cache(0)
{
}

HttpRequest::~HttpRequest()
{
    abort();
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(HttpRequest) : Refine.<commit_after>/*
 * Copyright 2011 Esrille Inc.
 *
 * Licensed 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.
 */

#include "HTTPRequest.h"

#include <iostream>
#include <string>

#include "utf.h"

#include "url/URI.h"
#include "http/HTTPCache.h"
#include "http/HTTPConnection.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

int HttpRequest::getContentDescriptor()
{
    return fdContent;  // TODO: call dup internally?
}

std::FILE* HttpRequest::openFile()
{
    if (fdContent == -1)
        return 0;
    std::FILE* file = fdopen(dup(fdContent), "rb");
    if (!file)
        return 0;
    rewind(file);
    return file;
}

std::fstream& HttpRequest::getContent()
{
    if (content.is_open())
        return content;

    char filename[] = "/tmp/esXXXXXX";
    fdContent = mkstemp(filename);
    if (fdContent == -1)
        return content;
    content.open(filename, std::ios_base::trunc | std::ios_base::in | std::ios_base::out | std::ios::binary);
    remove(filename);

    return content;
}

void HttpRequest::notify(bool error)
{
    readyState = DONE;
    errorFlag = error;
    if (cache)
        cache->notify(this, error);
    if (handler)
        handler();
}

void HttpRequest::open(const std::u16string& method, const std::u16string& urlString)
{
    URL url(base, urlString);
    request.open(utfconv(method), url);
    readyState = OPENED;
}

void HttpRequest::setRequestHeader(const std::u16string& header, const std::u16string& value)
{
    request.setHeader(utfconv(header), utfconv(value));
}

void HttpRequest::constructResponseFromCache()
{
    readyState = DONE;
    errorFlag = false;
    response.update(cache->getResponseMessage());

    // TODO: deal with partial...
    int fd = cache->getContentDescriptor();
    if (0 <= fd)
        fdContent = dup(fd);

    if (handler)
        handler();
}

void HttpRequest::send()
{
    if (request.getURL().isEmpty()) {
        readyState = DONE;
        if (handler)
            handler();
        return;
    }

    cache = HttpCacheManager::getInstance().send(this);
    if (!cache || cache->isBusy())
        return;
    constructResponseFromCache();
}

void HttpRequest::abort()
{
    if (readyState == UNSENT)
        return;

    // TODO: implement more details.
    clearHanndler();
    if (cache)
        cache->abort(this);
    else {
        HttpConnectionManager& manager = HttpConnectionManager::getInstance();
        manager.abort(this);
    }
    readyState = UNSENT;
    errorFlag = false;
    request.clear();
    response.clear();
    if (content.is_open())
        content.close();
    if (0 <= fdContent) {
        close(fdContent);
        fdContent = -1;
    }
}

unsigned short HttpRequest::getStatus() const
{
    return response.getStatus();
}

const std::string& HttpRequest::getStatusText() const
{
    return response.getStatusText();
}

const std::string HttpRequest::getResponseHeader(std::u16string header) const
{
    return response.getResponseHeader(utfconv(header));
}

const std::string& HttpRequest::getAllResponseHeaders() const
{
    return response.getAllResponseHeaders();
}

HttpRequest::HttpRequest(const std::u16string& base) :
    base(base),
    readyState(UNSENT),
    errorFlag(false),
    fdContent(-1),
    cache(0)
{
}

HttpRequest::~HttpRequest()
{
    abort();
}

}}}}  // org::w3c::dom::bootstrap
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <stdint.h>
#include "../util/MatasanoConverter.h"
#include "../util/MatasanoUtil.h"
#include "../util/StringTesting.h"

#define PUNCTUATION_THRESHOLD 5

//The hex encoded string:
//
//1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
//... has been XOR'd against a single character. Find the key, decrypt the message.
//
//You can do this by hand. But don't: write code to do it for you.
//
//How? Devise some method for "scoring" a piece of English plaintext.
//Character frequency is a good metric. Evaluate each output and choose the one with the best score.

std::vector<TestString> TestStringVectorSetup(std::vector<uint8_t> input_bytes) {
	std::string xor_output_string;
	uint8_t xor_character;
	std::vector<uint8_t> xor_vector;
	std::vector<uint8_t> xor_output_bytes;
	std::vector<TestString> output_strings;

	xor_vector = CreateSingleCharacterXorVector(0, input_bytes.size());
	xor_output_bytes = XorByteVectors(input_bytes, xor_vector);
	xor_output_string = StringFromByteVector(xor_output_bytes, "ASCII");
	output_strings.push_back(CreateTestString(xor_output_string, xor_character));

	for (xor_character = 1; xor_character != 0; xor_character++) {
		//test all potential i's
		xor_vector = CreateSingleCharacterXorVector(xor_character, input_bytes.size());
		xor_output_bytes = XorByteVectors(input_bytes, xor_vector);
		xor_output_string = StringFromByteVector(xor_output_bytes, "ASCII");
		output_strings.push_back(CreateTestString(xor_output_string, xor_character));
	}

	return output_strings;
}

int main() {
	std::string input_string = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
	std::vector<uint8_t> input_byte_vector;
	std::vector<TestString> potential_strings;

	input_byte_vector = ByteVectorFromString(input_string, "hex");;

	potential_strings = TestStringVectorSetup(input_byte_vector);

	potential_strings = FilterNonPrintable(potential_strings);
	std::cout << "Remaining Keys (initial filter): " << potential_strings.size() << std::endl;

	potential_strings = FilterExcessivePunctuation(potential_strings, PUNCTUATION_THRESHOLD);
	std::cout << "Remaining Keys (excessive punctuation filter): " << potential_strings.size() << std::endl;

	for (uint16_t i = 0; i < potential_strings.size(); i++) {
		std::cout << "Key used: " << (unsigned) potential_strings[i].key << std::endl << potential_strings[i].s << std::endl;
	}

	std::cout << "Remaining Keys: " << potential_strings.size() << std::endl;

	return 0;
}<commit_msg>Initialise xor_character in TestStringVectorSetup<commit_after>#include <iostream>
#include <string>
#include <stdint.h>
#include "../util/MatasanoConverter.h"
#include "../util/MatasanoUtil.h"
#include "../util/StringTesting.h"

#define PUNCTUATION_THRESHOLD 5

//The hex encoded string:
//
//1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736
//... has been XOR'd against a single character. Find the key, decrypt the message.
//
//You can do this by hand. But don't: write code to do it for you.
//
//How? Devise some method for "scoring" a piece of English plaintext.
//Character frequency is a good metric. Evaluate each output and choose the one with the best score.

std::vector<TestString> TestStringVectorSetup(std::vector<uint8_t> input_bytes) {
	std::string xor_output_string;
	uint8_t xor_character = 0;
	std::vector<uint8_t> xor_vector;
	std::vector<uint8_t> xor_output_bytes;
	std::vector<TestString> output_strings;

	xor_vector = CreateSingleCharacterXorVector(xor_character, input_bytes.size());
	xor_output_bytes = XorByteVectors(input_bytes, xor_vector);
	xor_output_string = StringFromByteVector(xor_output_bytes, "ASCII");
	output_strings.push_back(CreateTestString(xor_output_string, xor_character));

	for (xor_character = 1; xor_character != 0; xor_character++) {
		//test all potential i's
		xor_vector = CreateSingleCharacterXorVector(xor_character, input_bytes.size());
		xor_output_bytes = XorByteVectors(input_bytes, xor_vector);
		xor_output_string = StringFromByteVector(xor_output_bytes, "ASCII");
		output_strings.push_back(CreateTestString(xor_output_string, xor_character));
	}

	return output_strings;
}

int main() {
	std::string input_string = "1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736";
	std::vector<uint8_t> input_byte_vector;
	std::vector<TestString> potential_strings;

	input_byte_vector = ByteVectorFromString(input_string, "hex");;

	potential_strings = TestStringVectorSetup(input_byte_vector);

	potential_strings = FilterNonPrintable(potential_strings);
	std::cout << "Remaining Keys (initial filter): " << potential_strings.size() << std::endl;

	potential_strings = FilterExcessivePunctuation(potential_strings, PUNCTUATION_THRESHOLD);
	std::cout << "Remaining Keys (excessive punctuation filter): " << potential_strings.size() << std::endl;

	for (uint16_t i = 0; i < potential_strings.size(); i++) {
		std::cout << "Key used: " << (unsigned) potential_strings[i].key << std::endl << potential_strings[i].s << std::endl;
	}

	std::cout << "Remaining Keys: " << potential_strings.size() << std::endl;
	getchar();
	return 0;
}<|endoftext|>