<commit_before>/*
 * Copyright 2013-2014 <NAME> (https://github.com/mikemag)
 *
 * 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 <algorithm>
#include <boost/range/adaptor/reversed.hpp>
#include <cassert>
#include <fstream>
#include <iostream>
#include <time.h>

#include "gcode-writer.h"
#include "MonkeyCAMConfig.h"

namespace MonkeyCAM {

using std::string;
using std::vector;

GCodeWriter::GCodeWriter(string filename, Tool const& tool,
                         ZeroZ zeroHeight, XYOrigin origin,
                         int normalSpeed, MCFixed rapidHeight)
    : m_filename(filename)
    , m_tool(tool)
    , m_defaultSpeed(normalSpeed)
    , m_rapidHeight(rapidHeight)
    , m_zeroHeight(zeroHeight)
    , m_xyOrigin(origin)
    , m_incremental(false)
    , m_currentSpeed(0)
    , m_firstMovement(true)
    , m_lowerBoundingBox(Point::MaxPoint)
    , m_upperBoundingBox(Point::MinPoint)
{
  headerBlock();
  startBlock();
}

// Simple word-wrapped comments
void GCodeWriter::headerComment(string s, int indent) {
  commentWrapped(m_headerComments, s, indent);
}

void GCodeWriter::comment(string s, int indent) {
  commentWrapped(m_lines, s, indent);
}

// Comments with specific formatting. Will be truncated to 76 chars.
void GCodeWriter::headerCommentF(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  comment(m_headerComments, fmt, args);
  va_end(args);
}

void GCodeWriter::commentF(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  comment(m_lines, fmt, args);
  va_end(args);
}

// Word-wrap the string, and add a comment for each wrapped
// line. Indent is a hanging indent, only applied to lines after the
// first.
void GCodeWriter::commentWrapped(GCodeLines& lines, string s, int indent) {
  if (s.size() == 0) {
    comment(lines, s.c_str());
    return;
  }
  const string::size_type maxWidth = 76;
  string line;
  string::size_type consumed = 0;
  while (consumed != s.size()) {
    auto spcPos = s.find(' ', consumed);
    if (spcPos == string::npos) spcPos = s.size(); // End of string
    if ((spcPos - consumed) == 0) {
      consumed++;
      continue; // Eat consecutive spaces
    }
    if ((spcPos - consumed) > maxWidth) { // Word is too long for any line
      spcPos = consumed + maxWidth -
        ((line.size() < maxWidth) ? line.size() : 0);
    }
    if (line.size() + (spcPos - consumed) > maxWidth) { // No room, dump it
      comment(lines, line.c_str());
      line.clear();
      line.append(indent, ' ');
    }
    line.append(s, consumed, spcPos - consumed);
    if (line.size() < maxWidth) {
      line.append(" ");
    }
    consumed = spcPos;
    if ((spcPos == s.size() - 1) || s[spcPos] == ' ') consumed++;
  }
  if (line.size() > 0) comment(lines, line.c_str());
}

void GCodeWriter::comment(GCodeLines& lines, const char* s) {
  char buff[81];
  assert(!strchr(s, '(') && !strchr(s, ')'));
  snprintf(buff, sizeof(buff), "( %-76s )", s);
  lines.push_back(string(buff));
}

void GCodeWriter::comment(GCodeLines& lines, const char* fmt, va_list args) {
  char buff[256];
  vsnprintf(buff, sizeof(buff), fmt, args);
  comment(lines, buff);
}

void GCodeWriter::headerBlock() {
  time_t rawtime;
  time(&rawtime);
  struct tm* timeinfo = localtime(&rawtime);
  char timebuff[80];
  strftime(timebuff, sizeof(timebuff), "%F %X", timeinfo);
  headerComment(m_filename);
  headerCommentF("Generated by MonkeyCAM v%d.%d.%d at %s",
                 MonkeyCAM_VERSION_MAJOR,
                 MonkeyCAM_VERSION_MINOR,
                 MonkeyCAM_VERSION_PATCH,
                 timebuff);
  headerComment();
  headerComment("This GCode program is provided on an \"AS IS\" BASIS WITHOUT "
                "WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
                "implied. You should inspect this program very carefully to "<commit_msg>Use time format flags actually supported in MinGW.<commit_after>/*
 * Copyright 2013-2014 <NAME> (https://github.com/mikemag)
 *
 * 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 <algorithm>
#include <boost/range/adaptor/reversed.hpp>
#include <cassert>
#include <fstream>
#include <iostream>
#include <time.h>

#include "gcode-writer.h"
#include "MonkeyCAMConfig.h"

namespace MonkeyCAM {

using std::string;
using std::vector;

GCodeWriter::GCodeWriter(string filename, Tool const& tool,
                         ZeroZ zeroHeight, XYOrigin origin,
                         int normalSpeed, MCFixed rapidHeight)
    : m_filename(filename)
    , m_tool(tool)
    , m_defaultSpeed(normalSpeed)
    , m_rapidHeight(rapidHeight)
    , m_zeroHeight(zeroHeight)
    , m_xyOrigin(origin)
    , m_incremental(false)
    , m_currentSpeed(0)
    , m_firstMovement(true)
    , m_lowerBoundingBox(Point::MaxPoint)
    , m_upperBoundingBox(Point::MinPoint)
{
  headerBlock();
  startBlock();
}

// Simple word-wrapped comments
void GCodeWriter::headerComment(string s, int indent) {
  commentWrapped(m_headerComments, s, indent);
}

void GCodeWriter::comment(string s, int indent) {
  commentWrapped(m_lines, s, indent);
}

// Comments with specific formatting. Will be truncated to 76 chars.
void GCodeWriter::headerCommentF(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  comment(m_headerComments, fmt, args);
  va_end(args);
}

void GCodeWriter::commentF(const char* fmt, ...) {
  va_list args;
  va_start(args, fmt);
  comment(m_lines, fmt, args);
  va_end(args);
}

// Word-wrap the string, and add a comment for each wrapped
// line. Indent is a hanging indent, only applied to lines after the
// first.
void GCodeWriter::commentWrapped(GCodeLines& lines, string s, int indent) {
  if (s.size() == 0) {
    comment(lines, s.c_str());
    return;
  }
  const string::size_type maxWidth = 76;
  string line;
  string::size_type consumed = 0;
  while (consumed != s.size()) {
    auto spcPos = s.find(' ', consumed);
    if (spcPos == string::npos) spcPos = s.size(); // End of string
    if ((spcPos - consumed) == 0) {
      consumed++;
      continue; // Eat consecutive spaces
    }
    if ((spcPos - consumed) > maxWidth) { // Word is too long for any line
      spcPos = consumed + maxWidth -
        ((line.size() < maxWidth) ? line.size() : 0);
    }
    if (line.size() + (spcPos - consumed) > maxWidth) { // No room, dump it
      comment(lines, line.c_str());
      line.clear();
      line.append(indent, ' ');
    }
    line.append(s, consumed, spcPos - consumed);
    if (line.size() < maxWidth) {
      line.append(" ");
    }
    consumed = spcPos;
    if ((spcPos == s.size() - 1) || s[spcPos] == ' ') consumed++;
  }
  if (line.size() > 0) comment(lines, line.c_str());
}

void GCodeWriter::comment(GCodeLines& lines, const char* s) {
  char buff[81];
  assert(!strchr(s, '(') && !strchr(s, ')'));
  snprintf(buff, sizeof(buff), "( %-76s )", s);
  lines.push_back(string(buff));
}

void GCodeWriter::comment(GCodeLines& lines, const char* fmt, va_list args) {
  char buff[256];
  vsnprintf(buff, sizeof(buff), fmt, args);
  comment(lines, buff);
}

void GCodeWriter::headerBlock() {
  time_t rawtime;
  time(&rawtime);
  struct tm* timeinfo = localtime(&rawtime);
  char timebuff[80];
  strftime(timebuff, sizeof(timebuff), "%Y-%m-%d %X", timeinfo);
  headerComment(m_filename);
  headerCommentF("Generated by MonkeyCAM v%d.%d.%d at %s",
                 MonkeyCAM_VERSION_MAJOR,
                 MonkeyCAM_VERSION_MINOR,
                 MonkeyCAM_VERSION_PATCH,
                 timebuff);
  headerComment();
  headerComment("This GCode program is provided on an \"AS IS\" BASIS WITHOUT "
                "WARRANTIES OR CONDITIONS OF ANY KIND, either express or "
                "implied. You should inspect this program very carefully to "
{'fraction_non_alphanumeric': 0.13254668346889678, 'fraction_numerical': 0.007331882231641654, 'mean_word_length': 3.371557336004006, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 23, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2446352', 'n_tokens_mistral': 2879, 'n_tokens_neox': 2797, 'n_words': 793}