<commit_before>#include "scimed/wx.h"

class MyApp: public wxApp
{
 public:
  virtual bool OnInit();
};

class MyFrame: public wxFrame
{
 public:
  MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
 private:
  void OnHello(wxCommandEvent& event);
  void OnExit(wxCommandEvent& event);
  void OnAbout(wxCommandEvent& event);
};

enum
{
  ID_Hello = 1
};

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
  MyFrame *frame = new MyFrame( "Hello World", wxPoint(50, 50), wxSize(450, 340) );
  frame->Show( true );
  return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
    : wxFrame(NULL, wxID_ANY, title, pos, size)
{
  wxMenu *menuFile = new wxMenu;
  menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
                   "Help string shown in status bar for this menu item");
  menuFile->AppendSeparator();
  menuFile->Append(wxID_EXIT);
  wxMenu *menuHelp = new wxMenu;
  menuHelp->Append(wxID_ABOUT);
  wxMenuBar *menuBar = new wxMenuBar;
  menuBar->Append( menuFile, "&File" );
  menuBar->Append( menuHelp, "&Help" );
  SetMenuBar( menuBar );
  CreateStatusBar();
  SetStatusText( "Welcome to wxWidgets!" );

  Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnExit, this, wxID_EXIT);
  Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnAbout, this, wxID_ABOUT);
  Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnHello, this, ID_Hello);
}

void MyFrame::OnExit(wxCommandEvent& event)
{
  Close( true );
}

void MyFrame::OnAbout(wxCommandEvent& event)
{
  wxMessageBox( "This is a wxWidgets' Hello world sample",
                "About Hello World", wxOK | wxICON_INFORMATION );
}

void MyFrame::OnHello(wxCommandEvent& event)
{
  wxLogMessage("Hello world from wxWidgets!");
}<commit_msg>scimed basics<commit_after>#include "scimed/wx.h"

// todo:
// add loading, zooming and panning in image
// add loading/saving and specifying areas
// add preview pane

class MyApp: public wxApp
{
 public:
  virtual bool OnInit();
};

class MyFrame: public wxFrame
{
 public:
  MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
 private:
  void OnHello(wxCommandEvent& event);
  void OnExit(wxCommandEvent& event);
  void OnAbout(wxCommandEvent& event);
};

enum
{
  ID_Hello = 1
};

wxIMPLEMENT_APP(MyApp);

bool MyApp::OnInit()
{
  MyFrame *frame = new MyFrame( "Scimed", wxPoint(50, 50), wxSize(450, 340) );
  frame->Show( true );
  return true;
}

MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
    : wxFrame(NULL, wxID_ANY, title, pos, size)
{
  wxMenu *menuFile = new wxMenu;
  menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
                   "Help string shown in status bar for this menu item");
  menuFile->AppendSeparator();
  menuFile->Append(wxID_EXIT);

  wxMenu *menuHelp = new wxMenu;
  menuHelp->Append(wxID_ABOUT);

  wxMenuBar *menuBar = new wxMenuBar;
  menuBar->Append( menuFile, "&File" );
  menuBar->Append( menuHelp, "&Help" );
  SetMenuBar( menuBar );

  CreateStatusBar();
  SetStatusText( "Welcome to wxWidgets!" );

  Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnExit, this, wxID_EXIT);
  Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnAbout, this, wxID_ABOUT);
  Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnHello, this, ID_Hello);
}

void MyFrame::OnExit(wxCommandEvent& event)
{
  Close( true );
}

void MyFrame::OnAbout(wxCommandEvent& event)
{
  wxMessageBox( "Scimed - the Scalable Image Editor",
                "About Scimed", wxOK | wxICON_INFORMATION );
}

void MyFrame::OnHello(wxCommandEvent& event)
{
  wxLogMessage("Hello world from wxWidgets!");
}<|endoftext|>


<commit_before>#include "image.h"
#include <cstdint>
#include <cstring>
#include <algorithm>

#pragma pack(push, 1) // All structs in this file are assumed to be byte-packed
namespace rsimpl
{
    //////////////////////////////
    // Naive unpacking routines //
    //////////////////////////////

    void unpack_subrect(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.streams.size() == 1 && mode.streams[0].width <= mode.width && mode.streams[0].height <= mode.height);

        auto in = reinterpret_cast<const uint8_t *>(source);
        auto out = reinterpret_cast<uint8_t *>(dest[0]);

        const size_t in_stride = get_image_size(mode.width, 1, mode.streams[0].format), out_stride = get_image_size(mode.streams[0].width, 1, mode.streams[0].format);
        for(int i=0; i<mode.streams[0].height; ++i)
        {
            memcpy(out, in, out_stride);
            out += out_stride;
            in += in_stride;
        }
    }

    /////////////////////////////
    // YUY2 unpacking routines //
    /////////////////////////////

    struct yuy2_double_pixel
    {
        uint8_t bytes[4];
        int y0() const { return bytes[0] - 16; }
        int y1() const { return bytes[2] - 16; }
        int u() const { return bytes[1] - 128; }
        int v() const { return bytes[3] - 128; }
    };
    static_assert(sizeof(yuy2_double_pixel) == 4, "packing error");

    inline uint8_t clamp_byte(int v) { return v < 0 ? 0 : v > 255 ? 255 : v; }
    inline uint8_t yuv_to_r(int y, int u, int v) { return clamp_byte((128 + 298 * y           + 409 * v) >> 8); }
    inline uint8_t yuv_to_g(int y, int u, int v) { return clamp_byte((128 + 298 * y - 100 * u - 208 * v) >> 8); }
    inline uint8_t yuv_to_b(int y, int u, int v) { return clamp_byte((128 + 298 * y + 516 * u          ) >> 8); }

    void unpack_rgb_from_yuy2(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'YUY2' && mode.streams.size() == 1 && mode.streams[0].width == mode.width && mode.streams[0].height == mode.height && mode.streams[0].format == RS_FORMAT_RGB);

        auto in = reinterpret_cast<const yuy2_double_pixel *>(source);
        auto out = reinterpret_cast<uint8_t *>(dest[0]);

        for (int y = 0; y < mode.height; ++y)
        {
            for (int x = 0; x < mode.width; x += 2)
            {
                *out++ = yuv_to_r(in->y0(), in->u(), in->v());
                *out++ = yuv_to_g(in->y0(), in->u(), in->v());
                *out++ = yuv_to_b(in->y0(), in->u(), in->v());

                *out++ = yuv_to_r(in->y1(), in->u(), in->v());
                *out++ = yuv_to_g(in->y1(), in->u(), in->v());
                *out++ = yuv_to_b(in->y1(), in->u(), in->v());

                ++in;
            }
        }
    }

    void unpack_rgba_from_yuy2(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'YUY2' && mode.streams.size() == 1 && mode.streams[0].width == mode.width && mode.streams[0].height == mode.height && mode.streams[0].format == RS_FORMAT_RGBA);

        auto in = reinterpret_cast<const yuy2_double_pixel *>(source);
        auto out = reinterpret_cast<uint8_t *>(dest[0]);

        for (int y = 0; y < mode.height; ++y)
        {
            for (int x = 0; x < mode.width; x += 2)
            {
                *out++ = yuv_to_r(in->y0(), in->u(), in->v());
                *out++ = yuv_to_g(in->y0(), in->u(), in->v());
                *out++ = yuv_to_b(in->y0(), in->u(), in->v());
                *out++ = 255;

                *out++ = yuv_to_r(in->y1(), in->u(), in->v());
                *out++ = yuv_to_g(in->y1(), in->u(), in->v());
                *out++ = yuv_to_b(in->y1(), in->u(), in->v());
                *out++ = 255;

                ++in;
            }
        }
    }

    void unpack_bgr_from_yuy2(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'YUY2' && mode.streams.size() == 1 && mode.streams[0].width == mode.width && mode.streams[0].height == mode.height && mode.streams[0].format == RS_FORMAT_BGR);

        auto in = reinterpret_cast<const yuy2_double_pixel *>(source);
        auto out = reinterpret_cast<uint8_t *>(dest[0]);

        for (int y = 0; y < mode.height; ++y)
        {
            for (int x = 0; x < mode.width; x += 2)
            {
                *out++ = yuv_to_b(in->y0(), in->u(), in->v());
                *out++ = yuv_to_g(in->y0(), in->u(), in->v());
                *out++ = yuv_to_r(in->y0(), in->u(), in->v());

                *out++ = yuv_to_b(in->y1(), in->u(), in->v());
                *out++ = yuv_to_g(in->y1(), in->u(), in->v());
                *out++ = yuv_to_r(in->y1(), in->u(), in->v());

                ++in;
            }
        }
    }

    void unpack_bgra_from_yuy2(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'YUY2' && mode.streams.size() == 1 && mode.streams[0].width == mode.width && mode.streams[0].height == mode.height && mode.streams[0].format == RS_FORMAT_BGRA);

        auto in = reinterpret_cast<const yuy2_double_pixel *>(source);
        auto out = reinterpret_cast<uint8_t *>(dest[0]);

        for (int y = 0; y < mode.height; ++y)
        {
            for (int x = 0; x < mode.width; x += 2)
            {
                *out++ = yuv_to_b(in->y0(), in->u(), in->v());
                *out++ = yuv_to_g(in->y0(), in->u(), in->v());
                *out++ = yuv_to_r(in->y0(), in->u(), in->v());
                *out++ = 255;

                *out++ = yuv_to_b(in->y1(), in->u(), in->v());
                *out++ = yuv_to_g(in->y1(), in->u(), in->v());
                *out++ = yuv_to_r(in->y1(), in->u(), in->v());
                *out++ = 255;

                ++in;
            }
        }
    }

    //////////////////////////////////////
    // 2-in-1 format splitting routines //
    //////////////////////////////////////

    template<class SOURCE, class SPLIT_A, class SPLIT_B> void split_frame(void * dest[], const subdevice_mode & mode, const SOURCE * source, SPLIT_A split_a, SPLIT_B split_b)
    {
        assert(mode.streams.size() == 2 && mode.streams[0].width == mode.streams[1].width && mode.streams[0].height == mode.streams[1].height && mode.streams[0].width <= mode.width && mode.streams[0].height <= mode.height);
        auto a = reinterpret_cast<decltype(split_a(SOURCE())) *>(dest[0]);
        auto b = reinterpret_cast<decltype(split_b(SOURCE())) *>(dest[1]);
        for(int y=0; y<mode.streams[0].height; ++y)
        {
            for(int x=0; x<mode.streams[0].width; ++x)
            {
                *a++ = split_a(*source);
                *b++ = split_b(*source++);
            }
            source += mode.width - mode.streams[0].width;
        }
    }

    struct y12i_pixel
    {
        uint8_t rl : 8, rh : 4, ll : 4, lh : 8;
        int l() const { return lh << 4 | ll; }
        int r() const { return rh << 8 | rl; }
    };
    static_assert(sizeof(y12i_pixel) == 3, "packing error");

    void unpack_y8_y8_from_y12i(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'Y12I' && mode.streams.size() == 2 && mode.streams[0].format == RS_FORMAT_Y8 && mode.streams[1].format == RS_FORMAT_Y8);
        split_frame(dest, mode, reinterpret_cast<const y12i_pixel *>(source),
            [](const y12i_pixel & p) -> uint8_t { return p.l() >> 2; },  // We want to convert 10-bit data to 8-bit data
            [](const y12i_pixel & p) -> uint8_t { return p.r() >> 2; }); // Multiply by 1/4 to efficiently approximate 255/1023
    }

    void unpack_y16_y16_from_y12i(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'Y12I' && mode.streams.size() == 2 && mode.streams[0].format == RS_FORMAT_Y16 && mode.streams[1].format == RS_FORMAT_Y16);
        split_frame(dest, mode, reinterpret_cast<const y12i_pixel *>(source),
            [](const y12i_pixel & p) -> uint16_t { return p.l() << 6 | p.l() >> 4; },  // We want to convert 10-bit data to 16-bit data
            [](const y12i_pixel & p) -> uint16_t { return p.r() << 6 | p.r() >> 4; }); // Multiply by 64 1/16 to efficiently approximate 65535/1023
    }

    struct inri_pixel
    {
        uint16_t z16;
        uint8_t y8;
    };
    static_assert(sizeof(y12i_pixel) == 3, "packing error");

    void unpack_z16_y8_from_inri(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'INRI' && mode.streams.size() == 2 && mode.streams[0].format == RS_FORMAT_Z16 && mode.streams[1].format == RS_FORMAT_Y8);
        split_frame(dest, mode, reinterpret_cast<const inri_pixel *>(source),
            [](const inri_pixel & p) -> uint16_t { return p.z16; },
            [](const inri_pixel & p) -> uint8_t { return p.y8; });
    }
}
#pragma pack(pop)
<commit_msg>Simplify YUY2 unpacking routines.<commit_after>#include "image.h"
#include <cstdint>
#include <cstring>
#include <algorithm>

#pragma pack(push, 1) // All structs in this file are assumed to be byte-packed
namespace rsimpl
{
    //////////////////////////////
    // Naive unpacking routines //
    //////////////////////////////

    void unpack_subrect(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.streams.size() == 1 && mode.streams[0].width <= mode.width && mode.streams[0].height <= mode.height);

        auto in = reinterpret_cast<const uint8_t *>(source);
        auto out = reinterpret_cast<uint8_t *>(dest[0]);

        const size_t in_stride = get_image_size(mode.width, 1, mode.streams[0].format), out_stride = get_image_size(mode.streams[0].width, 1, mode.streams[0].format);
        for(int i=0; i<mode.streams[0].height; ++i)
        {
            memcpy(out, in, out_stride);
            out += out_stride;
            in += in_stride;
        }
    }

    /////////////////////////////
    // YUY2 unpacking routines //
    /////////////////////////////

    template<class UNPACK> void unpack_from_yuy2(void * dest[], const void * source, const subdevice_mode & mode, UNPACK unpack)
    {
        assert(mode.fourcc == 'YUY2' && mode.streams.size() == 1 && mode.streams[0].width == mode.width && mode.streams[0].height == mode.height);
        auto in = reinterpret_cast<const uint8_t *>(source);
        auto out = reinterpret_cast<uint8_t *>(dest[0]);
        for (int y = 0; y < mode.height; ++y)
        {
            for (int x = 0; x < mode.width; x += 2)
            {
                unpack(out, in[0]-16, in[1]-128, in[2]-16, in[3]-128);
                in += 4;
            }
        }
    }

    inline uint8_t clamp_byte(int v) { return v < 0 ? 0 : v > 255 ? 255 : v; }
    inline uint8_t yuv_to_r(int y, int u, int v) { return clamp_byte((128 + 298 * y           + 409 * v) >> 8); }
    inline uint8_t yuv_to_g(int y, int u, int v) { return clamp_byte((128 + 298 * y - 100 * u - 208 * v) >> 8); }
    inline uint8_t yuv_to_b(int y, int u, int v) { return clamp_byte((128 + 298 * y + 516 * u          ) >> 8); }

    void unpack_rgb_from_yuy2(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.streams.size() == 1 && mode.streams[0].format == RS_FORMAT_RGB);
        unpack_from_yuy2(dest, source, mode, [](uint8_t * & out, int y0, int u, int y1, int v)
        {
            *out++ = yuv_to_r(y0, u, v);
            *out++ = yuv_to_g(y0, u, v);
            *out++ = yuv_to_b(y0, u, v);

            *out++ = yuv_to_r(y1, u, v);
            *out++ = yuv_to_g(y1, u, v);
            *out++ = yuv_to_b(y1, u, v);
        });
    }

    void unpack_rgba_from_yuy2(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.streams.size() == 1 && mode.streams[0].format == RS_FORMAT_RGBA);
        unpack_from_yuy2(dest, source, mode, [](uint8_t * & out, int y0, int u, int y1, int v)
        {
            *out++ = yuv_to_r(y0, u, v);
            *out++ = yuv_to_g(y0, u, v);
            *out++ = yuv_to_b(y0, u, v);
            *out++ = 255;

            *out++ = yuv_to_r(y1, u, v);
            *out++ = yuv_to_g(y1, u, v);
            *out++ = yuv_to_b(y1, u, v);
            *out++ = 255;
        });
    }

    void unpack_bgr_from_yuy2(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.streams.size() == 1 && mode.streams[0].format == RS_FORMAT_BGR);
        unpack_from_yuy2(dest, source, mode, [](uint8_t * & out, int y0, int u, int y1, int v)
        {
            *out++ = yuv_to_b(y0, u, v);
            *out++ = yuv_to_g(y0, u, v);
            *out++ = yuv_to_r(y0, u, v);

            *out++ = yuv_to_b(y1, u, v);
            *out++ = yuv_to_g(y1, u, v);
            *out++ = yuv_to_r(y1, u, v);
        });
    }

    void unpack_bgra_from_yuy2(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.streams.size() == 1 && mode.streams[0].format == RS_FORMAT_BGRA);
        unpack_from_yuy2(dest, source, mode, [](uint8_t * & out, int y0, int u, int y1, int v)
        {
            *out++ = yuv_to_b(y0, u, v);
            *out++ = yuv_to_g(y0, u, v);
            *out++ = yuv_to_r(y0, u, v);
            *out++ = 255;

            *out++ = yuv_to_b(y1, u, v);
            *out++ = yuv_to_g(y1, u, v);
            *out++ = yuv_to_r(y1, u, v);
            *out++ = 255;
        });
    }

    //////////////////////////////////////
    // 2-in-1 format splitting routines //
    //////////////////////////////////////

    template<class SOURCE, class SPLIT_A, class SPLIT_B> void split_frame(void * dest[], const subdevice_mode & mode, const SOURCE * source, SPLIT_A split_a, SPLIT_B split_b)
    {
        assert(mode.streams.size() == 2 && mode.streams[0].width == mode.streams[1].width && mode.streams[0].height == mode.streams[1].height && mode.streams[0].width <= mode.width && mode.streams[0].height <= mode.height);
        auto a = reinterpret_cast<decltype(split_a(SOURCE())) *>(dest[0]);
        auto b = reinterpret_cast<decltype(split_b(SOURCE())) *>(dest[1]);
        for(int y=0; y<mode.streams[0].height; ++y)
        {
            for(int x=0; x<mode.streams[0].width; ++x)
            {
                *a++ = split_a(*source);
                *b++ = split_b(*source++);
            }
            source += mode.width - mode.streams[0].width;
        }
    }

    struct y12i_pixel
    {
        uint8_t rl : 8, rh : 4, ll : 4, lh : 8;
        int l() const { return lh << 4 | ll; }
        int r() const { return rh << 8 | rl; }
    };
    static_assert(sizeof(y12i_pixel) == 3, "packing error");

    void unpack_y8_y8_from_y12i(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'Y12I' && mode.streams.size() == 2 && mode.streams[0].format == RS_FORMAT_Y8 && mode.streams[1].format == RS_FORMAT_Y8);
        split_frame(dest, mode, reinterpret_cast<const y12i_pixel *>(source),
            [](const y12i_pixel & p) -> uint8_t { return p.l() >> 2; },  // We want to convert 10-bit data to 8-bit data
            [](const y12i_pixel & p) -> uint8_t { return p.r() >> 2; }); // Multiply by 1/4 to efficiently approximate 255/1023
    }

    void unpack_y16_y16_from_y12i(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'Y12I' && mode.streams.size() == 2 && mode.streams[0].format == RS_FORMAT_Y16 && mode.streams[1].format == RS_FORMAT_Y16);
        split_frame(dest, mode, reinterpret_cast<const y12i_pixel *>(source),
            [](const y12i_pixel & p) -> uint16_t { return p.l() << 6 | p.l() >> 4; },  // We want to convert 10-bit data to 16-bit data
            [](const y12i_pixel & p) -> uint16_t { return p.r() << 6 | p.r() >> 4; }); // Multiply by 64 1/16 to efficiently approximate 65535/1023
    }

    struct inri_pixel
    {
        uint16_t z16;
        uint8_t y8;
    };
    static_assert(sizeof(y12i_pixel) == 3, "packing error");

    void unpack_z16_y8_from_inri(void * dest[], const void * source, const subdevice_mode & mode)
    {
        assert(mode.fourcc == 'INRI' && mode.streams.size() == 2 && mode.streams[0].format == RS_FORMAT_Z16 && mode.streams[1].format == RS_FORMAT_Y8);
        split_frame(dest, mode, reinterpret_cast<const inri_pixel *>(source),
            [](const inri_pixel & p) -> uint16_t { return p.z16; },
            [](const inri_pixel & p) -> uint8_t { return p.y8; });
    }
}
#pragma pack(pop)
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <getopt.h>
#include <cstring>

#include <less/less/LessTokenizer.h>
#include <less/less/LessParser.h>
#include <less/css/CssWriter.h>
#include <less/css/CssPrettyWriter.h>
#include <less/stylesheet/Stylesheet.h>
#include <less/css/IOException.h>
#include <less/lessstylesheet/LessStylesheet.h>

using namespace std;

/**
 * /main Less CSS compiler, implemented in C++.
 *
 */

void usage () {
  cout <<
    "Usage: lessc [OPTION]... [FILE]\n"
    "\n"
    "   FILE				Less source file. If not given, source \
is read from stdin.\n"
    "   -h, --help			Show this message and exit.\n"
    "       --version		Print the program name and version.\n"
    "\n"
    "   -o, --output=<FILE>		Send output to FILE\n"
    "   -f, --format			Format output CSS with newlines and \
indentation. By default the output is unformatted.\n"
    "\n"
    "   -m, --source-map=[FILE]	Generate a source map.\n"
    "       --source-map-rootpath=<PATH>   PATH is prepended to the \
source file references in the source map, and also to the source map \
reference in the css output. \n"
    "       --source-map-basepath=<PATH>   PATH is removed from the \
source file references in the source map, and also from the source \
map reference in the css output.\n"
    "\n"
    "Example:\n"
    "   lessc in.less -o out.css\n"
    "\n"
    "Report bugs to: " PACKAGE_BUGREPORT "\n"
    PACKAGE_NAME " home page: <" PACKAGE_URL ">\n";
}

void version () {
  cout <<
    PACKAGE_STRING "\n"
    "Copyright 2012 Bram van der Kroef\n"
    "License: MIT License\n";
}

/**
 * Copy a given path to a new string and add a trailing slash if necessary.
 */
char* createPath(const char* path, size_t len) {
  size_t newlen = len +
    (path[len - 1] != '/' ? 1 : 0);
  char* p = new char[newlen + 1];
  std::strncpy(p, path, len);
  p[newlen - 1] = '/';
  p[newlen] = '\0';
  return p;
}

void parsePathList(const char* path, std::list<const char*>& paths) {
  const char* start = path;
  const char* end = path;
  size_t len;

  while((end = std::strchr(start, ':')) != NULL) {
    len = (end - start);
    // skip empty paths
    if (len > 0)
      paths.push_back(createPath(start, len));

    start = end + 1;
  }
  len = std::strlen(start);
  if (len > 0)
    paths.push_back(createPath(start, len));
}

bool parseInput(LessStylesheet &stylesheet,
                istream &in,
                const char* source,
                std::list<const char*> &sources,
                std::list<const char*> &includePaths){
  std::list<const char*>::iterator i;

  LessTokenizer tokenizer(in, source);
  LessParser parser(tokenizer, sources);
  parser.includePaths = &includePaths;

  try{
    parser.parseStylesheet(stylesheet);
  } catch(ParseException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what() << endl;

    return false;
  } catch(exception* e) {
    cerr << " Error: " << e->what() << endl;

    return false;
  }

  return true;
}
bool processStylesheet (LessStylesheet &stylesheet,
                  Stylesheet &css) {
  ProcessingContext context;

  try{
    stylesheet.process(css, context);

  } catch(ParseException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what() << endl;

    return false;

  } catch(ValueException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Error: " << e->what() << endl;

    return false;
  } catch(exception* e) {
    cerr << "Error: " << e->what() << endl;
    return false;
  }
  return true;
}

int main(int argc, char * argv[]){
  istream* in = &cin;
  ostream* out = &cout;
  bool formatoutput = false;
  char* source = NULL;
  string output = "-";
  LessStylesheet stylesheet;
  std::list<const char*> sources;
  Stylesheet css;
  CssWriter* writer;

  std::string sourcemap_file = "";
  ostream* sourcemap_s = NULL;
  SourceMapWriter* sourcemap = NULL;
  const char* sourcemap_rootpath = NULL;
  const char* sourcemap_basepath = NULL;
  const char* rootpath = NULL;

  std::list<const char*> includePaths;

  static struct option long_options[] = {
    {"version",    no_argument,       0, 1},
    {"help",       no_argument,       0, 'h'},
    {"output",     required_argument, 0, 'o'},
    {"format",     no_argument,       0, 'f'},
    {"source-map", optional_argument, 0, 'm'},
    {"source-map-rootpath", required_argument, 0, 2},
    {"source-map-basepath", required_argument, 0, 3},
    {"include-path", required_argument,        0, 'I'},
    {"rootpath", required_argument,  0, 4},
    {0,0,0,0}
  };

  try {
    int c, option_index;

    while((c = getopt_long(argc, argv, ":o:hfv:m::I:", long_options, &option_index)) != -1) {
      switch (c) {
      case 1:
        version();
        return 0;
      case 'h':
        usage();
        return 0;
      case 'o':
        output = optarg;
        out = new ofstream(optarg);
        break;
      case 'f':
        formatoutput = true;
        break;
      case 'm':
        if (optarg)
          sourcemap_file = optarg;
        else
          sourcemap_file = "-";
        break;

      case 2:
        sourcemap_rootpath = createPath(optarg, std::strlen(optarg));
        break;
      case 3:
        sourcemap_basepath = createPath(optarg, std::strlen(optarg));
        break;

      case 'I':
        parsePathList(optarg, includePaths);
        break;

      case 4:
        rootpath = createPath(optarg, std::strlen(optarg));
        break;

      }
    }

    if(argc - optind >= 1){

      source = new char[std::strlen(argv[optind]) + 1];
      std::strcpy(source, argv[optind]);

      in = new ifstream(source);
      if (in->fail() || in->bad())
        throw new IOException("Error opening file");

    } else if (sourcemap_file == "-") {
      throw new IOException("source-map option requires that \
a file name is specified for either the source map or the less \
source.");
    } else {
      source = new char[2];
      std::strcpy(source, "-");
    }

    if (sourcemap_file == "-") {
      sourcemap_file = source;
      sourcemap_file += ".map";
    }

    sources.push_back(source);

    if (parseInput(stylesheet, *in, source, sources, includePaths)) {
      if (sourcemap_file != "") {
        sourcemap_s = new ofstream(sourcemap_file.c_str());
        sourcemap = new SourceMapWriter(*sourcemap_s, sources, output.c_str(),
                                        sourcemap_rootpath,
                                        sourcemap_basepath);

        writer = formatoutput ? new CssPrettyWriter(*out, *sourcemap) :
          new CssWriter(*out, *sourcemap);
      } else {
        writer = formatoutput ? new CssPrettyWriter(*out) :
          new CssWriter(*out);
      }
      writer->rootpath = rootpath;

      if (!processStylesheet(stylesheet, css)) {
        return 1;
      }
      css.write(*writer);

      if (sourcemap != NULL) {
        if (sourcemap_basepath != NULL &&
            sourcemap_file.compare(0, std::strlen(sourcemap_basepath),
                                   sourcemap_basepath) == 0) {
          sourcemap_file.erase(0, std::strlen(sourcemap_basepath));
        }
        if (sourcemap_rootpath != NULL)
          sourcemap_file.insert(0, sourcemap_rootpath);

        writer->writeSourceMapUrl(sourcemap_file.c_str());
        sourcemap->close();
        delete sourcemap;
        if (sourcemap_s != NULL)
          delete sourcemap_s;
      }

      delete writer;
      *out << endl;
    } else
      return 1;
    delete [] source;

  } catch (IOException* e) {
    cerr << " Error: " << e->what() << endl;
    return 1;
  }

  return 0;
}
<commit_msg>Base source map filename on output css file rather than less file.<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <getopt.h>
#include <cstring>

#include <less/less/LessTokenizer.h>
#include <less/less/LessParser.h>
#include <less/css/CssWriter.h>
#include <less/css/CssPrettyWriter.h>
#include <less/stylesheet/Stylesheet.h>
#include <less/css/IOException.h>
#include <less/lessstylesheet/LessStylesheet.h>

using namespace std;

/**
 * /main Less CSS compiler, implemented in C++.
 *
 */

void usage () {
  cout <<
    "Usage: lessc [OPTION]... [FILE]\n"
    "\n"
    "   FILE				Less source file. If not given, source \
is read from stdin.\n"
    "   -h, --help			Show this message and exit.\n"
    "       --version		Print the program name and version.\n"
    "\n"
    "   -o, --output=<FILE>		Send output to FILE\n"
    "   -f, --format			Format output CSS with newlines and \
indentation. By default the output is unformatted.\n"
    "\n"
    "   -m, --source-map=[FILE]	Generate a source map.\n"
    "       --source-map-rootpath=<PATH>   PATH is prepended to the \
source file references in the source map, and also to the source map \
reference in the css output. \n"
    "       --source-map-basepath=<PATH>   PATH is removed from the \
source file references in the source map, and also from the source \
map reference in the css output.\n"
    "\n"
    "Example:\n"
    "   lessc in.less -o out.css\n"
    "\n"
    "Report bugs to: " PACKAGE_BUGREPORT "\n"
    PACKAGE_NAME " home page: <" PACKAGE_URL ">\n";
}

void version () {
  cout <<
    PACKAGE_STRING "\n"
    "Copyright 2012 Bram van der Kroef\n"
    "License: MIT License\n";
}

/**
 * Copy a given path to a new string and add a trailing slash if necessary.
 */
char* createPath(const char* path, size_t len) {
  size_t newlen = len +
    (path[len - 1] != '/' ? 1 : 0);
  char* p = new char[newlen + 1];
  std::strncpy(p, path, len);
  p[newlen - 1] = '/';
  p[newlen] = '\0';
  return p;
}

void parsePathList(const char* path, std::list<const char*>& paths) {
  const char* start = path;
  const char* end = path;
  size_t len;

  while((end = std::strchr(start, ':')) != NULL) {
    len = (end - start);
    // skip empty paths
    if (len > 0)
      paths.push_back(createPath(start, len));

    start = end + 1;
  }
  len = std::strlen(start);
  if (len > 0)
    paths.push_back(createPath(start, len));
}

bool parseInput(LessStylesheet &stylesheet,
                istream &in,
                const char* source,
                std::list<const char*> &sources,
                std::list<const char*> &includePaths) {
  std::list<const char*>::iterator i;

  LessTokenizer tokenizer(in, source);
  LessParser parser(tokenizer, sources);
  parser.includePaths = &includePaths;

  try{
    parser.parseStylesheet(stylesheet);
  } catch(ParseException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what() << endl;

    return false;
  } catch(exception* e) {
    cerr << " Error: " << e->what() << endl;

    return false;
  }

  return true;
}

bool processStylesheet (LessStylesheet &stylesheet,
                        Stylesheet &css) {
  ProcessingContext context;

  try{
    stylesheet.process(css, context);

  } catch(ParseException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what() << endl;
    return false;

  } catch(ValueException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Error: " << e->what() << endl;
    return false;

  } catch(exception* e) {

    cerr << "Error: " << e->what() << endl;
    return false;
  }
  return true;
}

int main(int argc, char * argv[]){
  istream* in = &cin;
  ostream* out = &cout;
  bool formatoutput = false;
  char* source = NULL;
  string output = "-";
  LessStylesheet stylesheet;
  std::list<const char*> sources;
  Stylesheet css;
  CssWriter* writer;

  std::string sourcemap_file = "";
  ostream* sourcemap_s = NULL;
  SourceMapWriter* sourcemap = NULL;
  const char* sourcemap_rootpath = NULL;
  const char* sourcemap_basepath = NULL;
  const char* rootpath = NULL;

  std::list<const char*> includePaths;

  static struct option long_options[] = {
    {"version",    no_argument,       0, 1},
    {"help",       no_argument,       0, 'h'},
    {"output",     required_argument, 0, 'o'},
    {"format",     no_argument,       0, 'f'},
    {"source-map", optional_argument, 0, 'm'},
    {"source-map-rootpath", required_argument, 0, 2},
    {"source-map-basepath", required_argument, 0, 3},
    {"include-path", required_argument,        0, 'I'},
    {"rootpath", required_argument,  0, 4},
    {0,0,0,0}
  };

  try {
    int c, option_index;

    while((c = getopt_long(argc, argv, ":o:hfv:m::I:", long_options, &option_index)) != -1) {
      switch (c) {
      case 1:
        version();
        return 0;

      case 'h':
        usage();
        return 0;

      case 'o':
        output = optarg;
        out = new ofstream(optarg);
        break;

      case 'f':
        formatoutput = true;
        break;

      case 'm':
        if (optarg)
          sourcemap_file = optarg;
        else
          sourcemap_file = "-";
        break;

      case 2:
        sourcemap_rootpath = createPath(optarg, std::strlen(optarg));
        break;

      case 3:
        sourcemap_basepath = createPath(optarg, std::strlen(optarg));
        break;

      case 'I':
        parsePathList(optarg, includePaths);
        break;

      case 4:
        rootpath = createPath(optarg, std::strlen(optarg));
        break;

      }
    }

    if (argc - optind >= 1) {

      source = new char[std::strlen(argv[optind]) + 1];
      std::strcpy(source, argv[optind]);

      in = new ifstream(source);
      if (in->fail() || in->bad())
        throw new IOException("Error opening file");

    }  else {

      source = new char[2];
      std::strcpy(source, "-");

    }

    if (sourcemap_file == "-") {
      if (output == "-") {
        throw new IOException("source-map option requires that \
a file name is specified for either the source map or the css \
output file.");
      } else {
        sourcemap_file = output;
        sourcemap_file += ".map";
      }
    }

    sources.push_back(source);

    if (parseInput(stylesheet, *in, source, sources, includePaths)) {
      if (sourcemap_file != "") {
        sourcemap_s = new ofstream(sourcemap_file.c_str());
        sourcemap = new SourceMapWriter(*sourcemap_s, sources, output.c_str(),
                                        sourcemap_rootpath,
                                        sourcemap_basepath);

        writer = formatoutput ? new CssPrettyWriter(*out, *sourcemap) :
          new CssWriter(*out, *sourcemap);
      } else {
        writer = formatoutput ? new CssPrettyWriter(*out) :
          new CssWriter(*out);
      }
      writer->rootpath = rootpath;

      if (!processStylesheet(stylesheet, css)) {
        return 1;
      }
      css.write(*writer);

      if (sourcemap != NULL) {
        if (sourcemap_basepath != NULL &&
            sourcemap_file.compare(0, std::strlen(sourcemap_basepath),
                                   sourcemap_basepath) == 0) {
          sourcemap_file.erase(0, std::strlen(sourcemap_basepath));
        }
        if (sourcemap_rootpath != NULL)
          sourcemap_file.insert(0, sourcemap_rootpath);

        writer->writeSourceMapUrl(sourcemap_file.c_str());
        sourcemap->close();
        delete sourcemap;
        if (sourcemap_s != NULL)
          delete sourcemap_s;
      }

      delete writer;
      *out << endl;
    } else
      return 1;
    delete [] source;

  } catch (IOException* e) {
    cerr << " Error: " << e->what() << endl;
    return 1;
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Bram van der Kroef
 *
 * This file is part of LESS CSS Compiler.
 *
 * LESS CSS Compiler is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * LESS CSS Compiler is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LESS CSS Compiler.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Bram van der Kroef <bram@vanderkroef.net>
 */

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

#include "LessTokenizer.h"
#include "LessParser.h"
#include "value/ValueProcessor.h"
#include "CssWriter.h"
#include "CssPrettyWriter.h"
#include "ExtendCssWriter.h"
#include "Stylesheet.h"
#include "IOException.h"
#include "LessStylesheet.h"

#include <config.h>

#ifdef WITH_LIBGLOG
#include <glog/logging.h>
#endif

using namespace std;

/**
 * /main Less CSS compiler, implemented in C++.
 *
 */

void usage () {
  cout << "Usage: lessc [OPTION] FILE" << endl;
  cout << endl;
  cout << "   -o FILE	Send output to FILE" << endl;
  cout << "   -f    	Format output." << endl;
  cout << endl;
  cout << "Example:" << endl;
  cout << "   lessc in.less -o out.css" << endl;
}

bool parseInput(LessStylesheet &stylesheet, istream &in, const std::string &source){
  LessTokenizer tokenizer(in, source);
  LessParser parser(tokenizer);

  try{
    parser.parseStylesheet(stylesheet);
  } catch(ParseException* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what();
#else
    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what();
#endif

    return false;

  } catch(exception* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << "Line " << tokenizer.getLineNumber() << ", Column " <<
      tokenizer.getColumn() << " Error: " << e->what();
#else
    cerr << "Line " << tokenizer.getLineNumber() << ", Column " <<
      tokenizer.getColumn() << " Error: " << e->what();
#endif
    return false;
  }

  return true;
}
void writeOutput (ostream &out, LessStylesheet &stylesheet, bool format) {
  Stylesheet css;
  CssWriter *w1;
  w1 = format ? new CssPrettyWriter(out) : new CssWriter(out);

  try{
    stylesheet.process(css);

  } catch(ParseException* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what();
#else
    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what();
#endif

    return;
  } catch(exception* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << "Error: " << e->what();
#else
    cerr << "Error: " << e->what();
#endif
    return;
  }

  css.write(*w1);
  out << endl;
  delete w1;
}

int main(int argc, char * argv[]){
  istream* in = &cin;
  ostream* out = &cout;
  bool formatoutput = false;
  string source = "-";
  LessStylesheet stylesheet;

#ifdef WITH_LIBGLOG
  FLAGS_logtostderr = 1;
  google::InitGoogleLogging(argv[0]);
  VLOG(1) << "Start.";
#endif

  try {
    int c;
#ifdef WITH_LIBGLOG
    VLOG(3) << "argc: " << argc;
#endif

    while((c = getopt(argc, argv, ":o:hfv:")) != EOF) {
      switch (c) {
      case 'h':
        usage();
        return 0;
      case 'o':
        out = new ofstream(optarg);
        break;
      case 'f':
        formatoutput = true;
        break;
      case 'v':
        FLAGS_v = atoi(optarg);
        break;
      }
    }

    if(argc - optind >= 1){
#ifdef WITH_LIBGLOG
      VLOG(1) << argv[optind];
#endif

      in = new ifstream(argv[optind]);
      source = argv[optind];
      if (in->fail() || in->bad())
        throw new IOException("Error opening file");
    }

    if (parseInput(stylesheet, *in, source)) {
        writeOutput(*out, stylesheet, formatoutput);
    } else
      return 1;

  } catch (IOException* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << " Error: " << e->what();
#else
    cerr << " Error: " << e->what();
#endif
    return 1;
  }

  return 0;
}

<commit_msg>Added ProcessingContext to lessc.<commit_after>/*
 * Copyright 2012 Bram van der Kroef
 *
 * This file is part of LESS CSS Compiler.
 *
 * LESS CSS Compiler is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * LESS CSS Compiler is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LESS CSS Compiler.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Bram van der Kroef <bram@vanderkroef.net>
 */

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

#include "LessTokenizer.h"
#include "LessParser.h"
#include "CssWriter.h"
#include "CssPrettyWriter.h"
#include "Stylesheet.h"
#include "IOException.h"
#include "LessStylesheet.h"

#include <config.h>

#ifdef WITH_LIBGLOG
#include <glog/logging.h>
#endif

using namespace std;

/**
 * /main Less CSS compiler, implemented in C++.
 *
 */

void usage () {
  cout << "Usage: lessc [OPTION] FILE" << endl;
  cout << endl;
  cout << "   -o FILE	Send output to FILE" << endl;
  cout << "   -f    	Format output." << endl;
  cout << endl;
  cout << "Example:" << endl;
  cout << "   lessc in.less -o out.css" << endl;
}

bool parseInput(LessStylesheet &stylesheet, istream &in, const std::string &source){
  LessTokenizer tokenizer(in, source);
  LessParser parser(tokenizer);

  try{
    parser.parseStylesheet(stylesheet);
  } catch(ParseException* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what();
#else
    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what();
#endif

    return false;

  } catch(exception* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << "Line " << tokenizer.getLineNumber() << ", Column " <<
      tokenizer.getColumn() << " Error: " << e->what();
#else
    cerr << "Line " << tokenizer.getLineNumber() << ", Column " <<
      tokenizer.getColumn() << " Error: " << e->what();
#endif
    return false;
  }

  return true;
}
void writeOutput (ostream &out, LessStylesheet &stylesheet, bool format) {
  Stylesheet css;
  ProcessingContext context;
  CssWriter *w1;
  w1 = format ? new CssPrettyWriter(out) : new CssWriter(out);

  try{
    stylesheet.process(css, context);

  } catch(ParseException* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what();
#else
    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what();
#endif

    return;
  } catch(exception* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << "Error: " << e->what();
#else
    cerr << "Error: " << e->what();
#endif
    return;
  }

  css.write(*w1);
  out << endl;
  delete w1;
}

int main(int argc, char * argv[]){
  istream* in = &cin;
  ostream* out = &cout;
  bool formatoutput = false;
  string source = "-";
  LessStylesheet stylesheet;

#ifdef WITH_LIBGLOG
  FLAGS_logtostderr = 1;
  google::InitGoogleLogging(argv[0]);
  VLOG(1) << "Start.";
#endif

  try {
    int c;
#ifdef WITH_LIBGLOG
    VLOG(3) << "argc: " << argc;
#endif

    while((c = getopt(argc, argv, ":o:hfv:")) != EOF) {
      switch (c) {
      case 'h':
        usage();
        return 0;
      case 'o':
        out = new ofstream(optarg);
        break;
      case 'f':
        formatoutput = true;
        break;
      case 'v':
        FLAGS_v = atoi(optarg);
        break;
      }
    }

    if(argc - optind >= 1){
#ifdef WITH_LIBGLOG
      VLOG(1) << argv[optind];
#endif

      in = new ifstream(argv[optind]);
      source = argv[optind];
      if (in->fail() || in->bad())
        throw new IOException("Error opening file");
    }

    if (parseInput(stylesheet, *in, source)) {
        writeOutput(*out, stylesheet, formatoutput);
    } else
      return 1;

  } catch (IOException* e) {
#ifdef WITH_LIBGLOG
    LOG(ERROR) << " Error: " << e->what();
#else
    cerr << " Error: " << e->what();
#endif
    return 1;
  }

  return 0;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <getopt.h>
#include <cstring>

#include <less/less/LessTokenizer.h>
#include <less/less/LessParser.h>
#include <less/css/CssWriter.h>
#include <less/css/CssPrettyWriter.h>
#include <less/stylesheet/Stylesheet.h>
#include <less/css/IOException.h>
#include <less/lessstylesheet/LessStylesheet.h>

using namespace std;

/**
 * /main Less CSS compiler, implemented in C++.
 *
 */

void usage () {
  cout <<
    "Usage: lessc [OPTION]... [FILE]\n"
    "\n"
    "   FILE				Less source file. If not given, source \
is read from stdin.\n"
    "   -h, --help			Show this message and exit.\n"
    "       --version		Print the program name and version.\n"
    "\n"
    "   -o, --output=<FILE>		Send output to FILE\n"
    "   -f, --format			Format output CSS with newlines and \
indentation. By default the output is unformatted.\n"
    "\n"
    "   -m, --source-map=[FILE]	Generate a source map.\n"
    "       --source-map-rootpath=<PATH>   PATH is prepended to the \
source file references in the source map, and also to the source map \
reference in the css output. \n"
    "       --source-map-basepath=<PATH>   PATH is removed from the \
source file references in the source map, and also from the source \
map reference in the css output.\n"
    "\n"
    "Example:\n"
    "   lessc in.less -o out.css\n"
    "\n"
    "Report bugs to: " PACKAGE_BUGREPORT "\n"
    PACKAGE_NAME " home page: <" PACKAGE_URL ">\n";
}

void version () {
  cout <<
    PACKAGE_STRING "\n"
    "Copyright 2012 Bram van der Kroef\n"
    "License: MIT License\n";
}

/**
 * Copy a given path to a new string and add a trailing slash if necessary.
 */
char* createPath(const char* path, size_t len) {
  size_t newlen = len +
    (path[len - 1] != '/' ? 1 : 0);
  char* p = new char[newlen + 1];
  std::strncpy(p, path, len);
  p[newlen - 1] = '/';
  p[newlen] = '\0';
  return p;
}

void parsePathList(const char* path, std::list<const char*>& paths) {
  const char* start = path;
  const char* end = path;
  size_t len;

  while((end = std::strchr(start, ':')) != NULL) {
    len = (end - start);
    // skip empty paths
    if (len > 0)
      paths.push_back(createPath(start, len));

    start = end + 1;
  }
  len = std::strlen(start);
  if (len > 0)
    paths.push_back(createPath(start, len));
}

bool parseInput(LessStylesheet &stylesheet,
                istream &in,
                const char* source,
                std::list<const char*> &sources,
                std::list<const char*> &includePaths) {
  std::list<const char*>::iterator i;

  LessTokenizer tokenizer(in, source);
  LessParser parser(tokenizer, sources);
  parser.includePaths = &includePaths;

  try{
    parser.parseStylesheet(stylesheet);
  } catch(ParseException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what() << endl;

    return false;
  } catch(exception* e) {
    cerr << " Error: " << e->what() << endl;

    return false;
  }

  return true;
}

bool processStylesheet (LessStylesheet &stylesheet,
                        Stylesheet &css) {
  ProcessingContext context;

  try{
    stylesheet.process(css, context);

  } catch(ParseException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what() << endl;
    return false;

  } catch(ValueException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Error: " << e->what() << endl;
    return false;

  } catch(exception* e) {

    cerr << "Error: " << e->what() << endl;
    return false;
  }
  return true;
}

int main(int argc, char * argv[]){
  istream* in = &cin;
  ostream* out = &cout;
  bool formatoutput = false;
  char* source = NULL;
  string output = "-";
  LessStylesheet stylesheet;
  std::list<const char*> sources;
  Stylesheet css;
  CssWriter* writer;

  std::string sourcemap_file = "";
  ostream* sourcemap_s = NULL;
  SourceMapWriter* sourcemap = NULL;
  const char* sourcemap_rootpath = NULL;
  const char* sourcemap_basepath = NULL;
  const char* rootpath = NULL;

  std::list<const char*> includePaths;

  static struct option long_options[] = {
    {"version",    no_argument,       0, 1},
    {"help",       no_argument,       0, 'h'},
    {"output",     required_argument, 0, 'o'},
    {"format",     no_argument,       0, 'f'},
    {"source-map", optional_argument, 0, 'm'},
    {"source-map-rootpath", required_argument, 0, 2},
    {"source-map-basepath", required_argument, 0, 3},
    {"include-path", required_argument,        0, 'I'},
    {"rootpath", required_argument,  0, 4},
    {0,0,0,0}
  };

  try {
    int c, option_index;

    while((c = getopt_long(argc, argv, ":o:hfv:m::I:", long_options, &option_index)) != -1) {
      switch (c) {
      case 1:
        version();
        return 0;

      case 'h':
        usage();
        return 0;

      case 'o':
        output = optarg;
        out = new ofstream(optarg);
        break;

      case 'f':
        formatoutput = true;
        break;

      case 'm':
        if (optarg)
          sourcemap_file = optarg;
        else
          sourcemap_file = "-";
        break;

      case 2:
        sourcemap_rootpath = createPath(optarg, std::strlen(optarg));
        break;

      case 3:
        sourcemap_basepath = createPath(optarg, std::strlen(optarg));
        break;

      case 'I':
        parsePathList(optarg, includePaths);
        break;

      case 4:
        rootpath = createPath(optarg, std::strlen(optarg));
        break;

      }
    }

    if (argc - optind >= 1) {

      source = new char[std::strlen(argv[optind]) + 1];
      std::strcpy(source, argv[optind]);

      in = new ifstream(source);
      if (in->fail() || in->bad())
        throw new IOException("Error opening file");

    }  else {

      source = new char[2];
      std::strcpy(source, "-");

    }

    if (sourcemap_file == "-") {
      if (output == "-") {
        throw new IOException("source-map option requires that \
a file name is specified for either the source map or the css \
output file.");
      } else {
        sourcemap_file = output;
        sourcemap_file += ".map";
      }
    }

    sources.push_back(source);

    if (parseInput(stylesheet, *in, source, sources, includePaths)) {
      if (sourcemap_file != "") {
        sourcemap_s = new ofstream(sourcemap_file.c_str());
        sourcemap = new SourceMapWriter(*sourcemap_s, sources, output.c_str(),
                                        sourcemap_rootpath,
                                        sourcemap_basepath);

        writer = formatoutput ? new CssPrettyWriter(*out, *sourcemap) :
          new CssWriter(*out, *sourcemap);
      } else {
        writer = formatoutput ? new CssPrettyWriter(*out) :
          new CssWriter(*out);
      }
      writer->rootpath = rootpath;

      if (!processStylesheet(stylesheet, css)) {
        return 1;
      }
      css.write(*writer);

      if (sourcemap != NULL) {
        if (sourcemap_basepath != NULL &&
            sourcemap_file.compare(0, std::strlen(sourcemap_basepath),
                                   sourcemap_basepath) == 0) {
          sourcemap_file.erase(0, std::strlen(sourcemap_basepath));
        }
        if (sourcemap_rootpath != NULL)
          sourcemap_file.insert(0, sourcemap_rootpath);

        writer->writeSourceMapUrl(sourcemap_file.c_str());
        sourcemap->close();
        delete sourcemap;
        if (sourcemap_s != NULL)
          delete sourcemap_s;
      }

      delete writer;
      *out << endl;
    } else
      return 1;
    delete [] source;

  } catch (IOException* e) {
    cerr << " Error: " << e->what() << endl;
    return 1;
  }

  return 0;
}
<commit_msg>Add rootpath option in usage text.<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <getopt.h>
#include <cstring>

#include <less/less/LessTokenizer.h>
#include <less/less/LessParser.h>
#include <less/css/CssWriter.h>
#include <less/css/CssPrettyWriter.h>
#include <less/stylesheet/Stylesheet.h>
#include <less/css/IOException.h>
#include <less/lessstylesheet/LessStylesheet.h>

using namespace std;

/**
 * /main Less CSS compiler, implemented in C++.
 *
 */

void usage () {
  cout <<
    "Usage: lessc [OPTION]... [FILE]\n"
    "\n"
    "   FILE				Less source file. If not given, source \
is read from stdin.\n"
    "   -h, --help			Show this message and exit.\n"
    "       --version		Print the program name and version.\n"
    "\n"
    "   -o, --output=<FILE>		Send output to FILE\n"
    "   -f, --format			Format output CSS with newlines and \
indentation. By default the output is unformatted.\n"
    "\n"
    "   -m, --source-map=[FILE]	Generate a source map.\n"
    "       --source-map-rootpath=<PATH>   PATH is prepended to the \
source file references in the source map, and also to the source map \
reference in the css output. \n"
    "       --source-map-basepath=<PATH>   PATH is removed from the \
source file references in the source map, and also from the source \
map reference in the css output.\n"
    "       --rootpath=<PATH>           Prefix PATH to urls and import \
statements in output. \n"
    "\n"
    "Example:\n"
    "   lessc in.less -o out.css\n"
    "\n"
    "Report bugs to: " PACKAGE_BUGREPORT "\n"
    PACKAGE_NAME " home page: <" PACKAGE_URL ">\n";
}

void version () {
  cout <<
    PACKAGE_STRING "\n"
    "Copyright 2012 Bram van der Kroef\n"
    "License: MIT License\n";
}

/**
 * Copy a given path to a new string and add a trailing slash if necessary.
 */
char* createPath(const char* path, size_t len) {
  size_t newlen = len +
    (path[len - 1] != '/' ? 1 : 0);
  char* p = new char[newlen + 1];
  std::strncpy(p, path, len);
  p[newlen - 1] = '/';
  p[newlen] = '\0';
  return p;
}

void parsePathList(const char* path, std::list<const char*>& paths) {
  const char* start = path;
  const char* end = path;
  size_t len;

  while((end = std::strchr(start, ':')) != NULL) {
    len = (end - start);
    // skip empty paths
    if (len > 0)
      paths.push_back(createPath(start, len));

    start = end + 1;
  }
  len = std::strlen(start);
  if (len > 0)
    paths.push_back(createPath(start, len));
}

bool parseInput(LessStylesheet &stylesheet,
                istream &in,
                const char* source,
                std::list<const char*> &sources,
                std::list<const char*> &includePaths) {
  std::list<const char*>::iterator i;

  LessTokenizer tokenizer(in, source);
  LessParser parser(tokenizer, sources);
  parser.includePaths = &includePaths;

  try{
    parser.parseStylesheet(stylesheet);
  } catch(ParseException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what() << endl;

    return false;
  } catch(exception* e) {
    cerr << " Error: " << e->what() << endl;

    return false;
  }

  return true;
}

bool processStylesheet (LessStylesheet &stylesheet,
                        Stylesheet &css) {
  ProcessingContext context;

  try{
    stylesheet.process(css, context);

  } catch(ParseException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Parse Error: " << e->what() << endl;
    return false;

  } catch(ValueException* e) {

    cerr << e->getSource() << ": Line " << e->getLineNumber() << ", Column " <<
      e->getColumn() << " Error: " << e->what() << endl;
    return false;

  } catch(exception* e) {

    cerr << "Error: " << e->what() << endl;
    return false;
  }
  return true;
}

int main(int argc, char * argv[]){
  istream* in = &cin;
  ostream* out = &cout;
  bool formatoutput = false;
  char* source = NULL;
  string output = "-";
  LessStylesheet stylesheet;
  std::list<const char*> sources;
  Stylesheet css;
  CssWriter* writer;

  std::string sourcemap_file = "";
  ostream* sourcemap_s = NULL;
  SourceMapWriter* sourcemap = NULL;
  const char* sourcemap_rootpath = NULL;
  const char* sourcemap_basepath = NULL;
  const char* rootpath = NULL;

  std::list<const char*> includePaths;

  static struct option long_options[] = {
    {"version",    no_argument,       0, 1},
    {"help",       no_argument,       0, 'h'},
    {"output",     required_argument, 0, 'o'},
    {"format",     no_argument,       0, 'f'},
    {"source-map", optional_argument, 0, 'm'},
    {"source-map-rootpath", required_argument, 0, 2},
    {"source-map-basepath", required_argument, 0, 3},
    {"include-path", required_argument,        0, 'I'},
    {"rootpath", required_argument,  0, 4},
    {0,0,0,0}
  };

  try {
    int c, option_index;

    while((c = getopt_long(argc, argv, ":o:hfv:m::I:", long_options, &option_index)) != -1) {
      switch (c) {
      case 1:
        version();
        return 0;

      case 'h':
        usage();
        return 0;

      case 'o':
        output = optarg;
        out = new ofstream(optarg);
        break;

      case 'f':
        formatoutput = true;
        break;

      case 'm':
        if (optarg)
          sourcemap_file = optarg;
        else
          sourcemap_file = "-";
        break;

      case 2:
        sourcemap_rootpath = createPath(optarg, std::strlen(optarg));
        break;

      case 3:
        sourcemap_basepath = createPath(optarg, std::strlen(optarg));
        break;

      case 'I':
        parsePathList(optarg, includePaths);
        break;

      case 4:
        rootpath = createPath(optarg, std::strlen(optarg));
        break;

      }
    }

    if (argc - optind >= 1) {

      source = new char[std::strlen(argv[optind]) + 1];
      std::strcpy(source, argv[optind]);

      in = new ifstream(source);
      if (in->fail() || in->bad())
        throw new IOException("Error opening file.");

    }  else {

      source = new char[2];
      std::strcpy(source, "-");

    }

    if (sourcemap_file == "-") {
      if (output == "-") {
        throw new IOException("source-map option requires that \
a file name is specified for either the source map or the css \
output file.");
      } else {
        sourcemap_file = output;
        sourcemap_file += ".map";
      }
    }

    sources.push_back(source);

    if (parseInput(stylesheet, *in, source, sources, includePaths)) {
      if (sourcemap_file != "") {
        sourcemap_s = new ofstream(sourcemap_file.c_str());
        sourcemap = new SourceMapWriter(*sourcemap_s, sources, output.c_str(),
                                        sourcemap_rootpath,
                                        sourcemap_basepath);

        writer = formatoutput ? new CssPrettyWriter(*out, *sourcemap) :
          new CssWriter(*out, *sourcemap);
      } else {
        writer = formatoutput ? new CssPrettyWriter(*out) :
          new CssWriter(*out);
      }
      writer->rootpath = rootpath;

      if (!processStylesheet(stylesheet, css)) {
        return 1;
      }
      css.write(*writer);

      if (sourcemap != NULL) {
        if (sourcemap_basepath != NULL &&
            sourcemap_file.compare(0, std::strlen(sourcemap_basepath),
                                   sourcemap_basepath) == 0) {
          sourcemap_file.erase(0, std::strlen(sourcemap_basepath));
        }
        if (sourcemap_rootpath != NULL)
          sourcemap_file.insert(0, sourcemap_rootpath);

        writer->writeSourceMapUrl(sourcemap_file.c_str());
        sourcemap->close();
        delete sourcemap;
        if (sourcemap_s != NULL)
          delete sourcemap_s;
      }

      delete writer;
      *out << endl;
    } else
      return 1;
    delete [] source;

  } catch (IOException* e) {
    cerr << " Error: " << e->what() << endl;
    return 1;
  }

  return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "StdAfx.h"
#include "..\BatchEncoder.h"
#include "..\utilities\Utilities.h"
#include "WorkThread.h"

enum Mode { None = -1, Encode = 0, Transcode = 1 };

bool ConvertItem(CItemContext* pContext)
{
    bool bSuccess = false;
    TCHAR szCommandLine[(64 * 1024)];
    ZeroMemory(szCommandLine, sizeof(szCommandLine));

    // input path
    CString szInputFile = pContext->item->szPath;

    // output path
    CString szOutPath;
    if (pContext->pWorkerContext->pConfig->m_Options.bOutputPathChecked == false)
    {
        szOutPath = szInputFile;
        CString szToRemove = ::GetFileName(szInputFile);
        int nNewLenght = szOutPath.GetLength() - szToRemove.GetLength();
        szOutPath.Truncate(nNewLenght);
    }
    else
    {
        szOutPath = pContext->pWorkerContext->pConfig->m_Options.szOutputPath;
    }

    // output format
    int nEncoder = pContext->pWorkerContext->pConfig->m_Formats.GetFormatById(pContext->item->szFormatId);
    if (nEncoder == -1)
    {
        pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: can not find valid encoder by id."));
        return bSuccess;
    }

    CFormat& encoderFormat = pContext->pWorkerContext->pConfig->m_Formats.GetData(nEncoder);
    CPreset& encoderPreset = encoderFormat.m_Presets.GetData(pContext->item->nPreset);
    CString szEncoderExePath = encoderFormat.szPath;
    CString szEncoderOptions = encoderPreset.szOptions;

    // check input extensions
    CString szInputFileExt = ::GetFileExtension(szInputFile).MakeUpper();
    bool bIsValidEncoderInput = encoderFormat.IsValidInputExtension(szInputFileExt);

    // output path

    CString szEncoderExtension = encoderFormat.szOutputExtension;
    CString szName = pContext->item->szName + _T(".") + szEncoderExtension.MakeLower();
    CString szOutputFile;
    if (szOutPath.GetLength() >= 1)
    {
        if (szOutPath[szOutPath.GetLength() - 1] == '\\' || szOutPath[szOutPath.GetLength() - 1] == '/')
            szOutputFile = szOutPath + szName;
        else
            szOutputFile = szOutPath + _T("\\") + szName;
    }
    else
    {
        szOutputFile = szName;
    }

    // processing mode
    Mode nProcessingMode = Mode::None;
    if (bIsValidEncoderInput)
        nProcessingMode = Mode::Encode;
    else
        nProcessingMode = Mode::Transcode;

    bool bDecode = false;
    int nTool = -1;
    bool bUseInPipesEnc = false;
    bool bUseOutPipesEnc = false;
    bool bUseInPipesDec = false;
    bool bUseOutPipesDec = false;
    CString szOrgInputFile = szInputFile;
    CString szOrgOutputFile = szOutputFile;

    // decode before encoding
    if (nProcessingMode == Mode::Transcode)
    {
        int nDecoder = pContext->pWorkerContext->pConfig->m_Formats.GetDecoderByExtension(pContext->item->szExtension);
        if (nDecoder == -1)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: can not find valid decoder by extension."));
            return bSuccess;
        }

        CFormat& decoderFormat = pContext->pWorkerContext->pConfig->m_Formats.GetData(nDecoder);
        CPreset& decoderPreset = decoderFormat.m_Presets.GetData(decoderFormat.nDefaultPreset);
        CString szDecoderExePath = decoderFormat.szPath;
        CString szDecoderOptions = decoderPreset.szOptions;

        bIsValidEncoderInput = encoderFormat.IsValidInputExtension(decoderFormat.szOutputExtension);
        if (bIsValidEncoderInput == false)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: decoder output not supported by encoder."));
            return bSuccess;
        }

        if (pContext->pWorkerContext->pConfig->m_Options.bForceConsoleWindow == false)
        {
            // configure decoder input and output pipes
            bUseInPipesDec = decoderFormat.bInput;
            bUseOutPipesDec = decoderFormat.bOutput;
        }

        // input file is stdin
        if (bUseInPipesDec == true)
            szInputFile = _T("-");

        // output file is stdout
        if (bUseOutPipesDec == true)
            szOutputFile = _T("-");

        // TODO: bUseOutPipes == true than handle szOutputFile same as input file
        if (nProcessingMode == Mode::Transcode)
        {
            CString szDecoderExtension = decoderFormat.szOutputExtension;
            szOutputFile = szOutputFile + +_T(".") + szDecoderExtension.MakeLower();
        }

        // build full command line for decoder (DECODER-EXE + OPTIONS + INFILE + OUTFILE)
        // this is basic model, some of encoder may have different command-line structure
        CString szExecute;
        szExecute = decoderFormat.szTemplate;
        szExecute.Replace(_T("$EXE"), _T("\"$EXE\""));
        szExecute.Replace(_T("$EXE"), szDecoderExePath);
        szExecute.Replace(_T("$OPTIONS"), szDecoderOptions);
        szExecute.Replace(_T("$INFILE"), _T("\"$INFILE\""));
        szExecute.Replace(_T("$INFILE"), szInputFile);
        szExecute.Replace(_T("$OUTFILE"), _T("\"$OUTFILE\""));
        szExecute.Replace(_T("$OUTFILE"), szOutputFile);

        bDecode = true;
        nTool = pContext->pWorkerContext->pConfig->m_Formats.GetFormatById(decoderFormat.szId);
        if (nTool == -1)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: failed to get decoder by format id."));
            return bSuccess;
        }

        lstrcpy(szCommandLine, szExecute.GetBuffer(szExecute.GetLength()));

        pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Decoding..."));

        CFileContext context;
        context.pWorkerContext = pContext->pWorkerContext;
        context.szInputFile = szOrgInputFile;
        context.szOutputFile = szOrgOutputFile;
        context.szCommandLine = szCommandLine;
        context.nIndex = pContext->item->nId;
        context.bDecode = bDecode;
        context.nTool = nTool;
        context.bUseReadPipes = bUseInPipesDec;
        context.bUseWritePipes = bUseOutPipesDec;

        // TODO: when transcoding don't show time stats
        bool bResult = false;
        try
        {
            bResult = ::ConvertFile(&context);
        }
        catch (...)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: exception thrown while decoding."));
            pContext->pWorkerContext->Callback(pContext->item->nId, -1, true, true);
        }

        if (bResult == true)
        {
            if (pContext->pWorkerContext->pConfig->m_Options.bDeleteSourceFiles == true)
                ::DeleteFile(szOrgInputFile);
        }
        else
        {
            if (pContext->pWorkerContext->pConfig->m_Options.bDeleteOnError == true)
                ::DeleteFile(szOutputFile);

            if (pContext->pWorkerContext->bRunning == false)
                return bSuccess;

            if (pContext->pWorkerContext->pConfig->m_Options.bStopOnErrors == true)
                return bSuccess;

            // when transcoding we are skipping to next file no encoding can be done when decoding failed
            return bSuccess;
        }
    }

    if (pContext->pWorkerContext->bRunning == false)
        return bSuccess;

    if (pContext->pWorkerContext->pConfig->m_Options.bForceConsoleWindow == false)
    {
        // configure encoder input and output pipes
        bUseInPipesEnc = encoderFormat.bInput;
        bUseOutPipesEnc = encoderFormat.bOutput;
    }

    if (nProcessingMode == Mode::Encode)
    {
        // input file is stdin
        if (bUseInPipesEnc == true)
            szInputFile = _T("-");

        // output file is stdout
        if (bUseOutPipesEnc == true)
            szOutputFile = _T("-");
    }

    if (nProcessingMode == Mode::Transcode)
    {
        // input filename is decoded output filename
        szInputFile = szOutputFile;
        szOrgInputFile = szOutputFile;

        // restore output filename
        szOutputFile = szOrgOutputFile;

        // input file is stdin
        if (bUseInPipesEnc == true)
            szInputFile = _T("-");

        // output file is stdout
        if (bUseOutPipesEnc == true)
            szOutputFile = _T("-");
    }

    // encode
    if ((nProcessingMode == Mode::Encode) || (nProcessingMode == Mode::Transcode))
    {
        // build full command line for encoder (ENCODER-EXE + OPTIONS + INFILE + OUTFILE)
        // this is basic model, some of encoder may have different command-line structure
        CString szExecute;
        szExecute = encoderFormat.szTemplate;
        szExecute.Replace(_T("$EXE"), _T("\"$EXE\""));
        szExecute.Replace(_T("$EXE"), szEncoderExePath);
        szExecute.Replace(_T("$OPTIONS"), szEncoderOptions);
        szExecute.Replace(_T("$INFILE"), _T("\"$INFILE\""));
        szExecute.Replace(_T("$INFILE"), szInputFile);
        szExecute.Replace(_T("$OUTFILE"), _T("\"$OUTFILE\""));
        szExecute.Replace(_T("$OUTFILE"), szOutputFile);

        bDecode = false;
        nTool = pContext->pWorkerContext->pConfig->m_Formats.GetFormatById(encoderFormat.szId);
        if (nTool == -1)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: failed to get encoder by format id."));
            return bSuccess;
        }

        lstrcpy(szCommandLine, szExecute.GetBuffer(szExecute.GetLength()));

        pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Encoding..."));

        CFileContext context;
        context.pWorkerContext = pContext->pWorkerContext;
        context.szInputFile = szOrgInputFile;
        context.szOutputFile = szOrgOutputFile;
        context.szCommandLine = szCommandLine;
        context.nIndex = pContext->item->nId;
        context.bDecode = bDecode;
        context.nTool = nTool;
        context.bUseReadPipes = bUseInPipesEnc;
        context.bUseWritePipes = bUseOutPipesEnc;

        bool bResult = false;
        try
        {
            bResult = ::ConvertFile(&context);
        }
        catch (...)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: exception thrown while encoding."));
            pContext->pWorkerContext->Callback(pContext->item->nId, -1, true, true);
        }

        if (bResult == true)
        {
            bSuccess = true;
            if (pContext->pWorkerContext->pConfig->m_Options.bDeleteSourceFiles == true)
                ::DeleteFile(szOrgInputFile);
        }
        else
        {
            if (pContext->pWorkerContext->pConfig->m_Options.bDeleteOnError == true)
                ::DeleteFile(szOutputFile);
        }

        if (nProcessingMode == Mode::Transcode)
            ::DeleteFile(szOrgInputFile);
    }

    return bSuccess;
}
<commit_msg>Remove unused code<commit_after>// Copyright (c) Wiesław Šoltés. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#include "StdAfx.h"
#include "..\BatchEncoder.h"
#include "..\utilities\Utilities.h"
#include "WorkThread.h"

enum Mode { None = -1, Encode = 0, Transcode = 1 };

bool ConvertItem(CItemContext* pContext)
{
    bool bSuccess = false;
    TCHAR szCommandLine[(64 * 1024)];
    ZeroMemory(szCommandLine, sizeof(szCommandLine));

    // input path
    CString szInputFile = pContext->item->szPath;

    // output path
    CString szOutPath;
    if (pContext->pWorkerContext->pConfig->m_Options.bOutputPathChecked == false)
    {
        szOutPath = szInputFile;
        CString szToRemove = ::GetFileName(szInputFile);
        int nNewLenght = szOutPath.GetLength() - szToRemove.GetLength();
        szOutPath.Truncate(nNewLenght);
    }
    else
    {
        szOutPath = pContext->pWorkerContext->pConfig->m_Options.szOutputPath;
    }

    // output format
    int nEncoder = pContext->pWorkerContext->pConfig->m_Formats.GetFormatById(pContext->item->szFormatId);
    if (nEncoder == -1)
    {
        pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: can not find valid encoder by id."));
        return bSuccess;
    }

    CFormat& encoderFormat = pContext->pWorkerContext->pConfig->m_Formats.GetData(nEncoder);
    CPreset& encoderPreset = encoderFormat.m_Presets.GetData(pContext->item->nPreset);
    CString szEncoderExePath = encoderFormat.szPath;
    CString szEncoderOptions = encoderPreset.szOptions;

    // check input extensions
    CString szInputFileExt = ::GetFileExtension(szInputFile).MakeUpper();
    bool bIsValidEncoderInput = encoderFormat.IsValidInputExtension(szInputFileExt);

    // output path

    CString szEncoderExtension = encoderFormat.szOutputExtension;
    CString szName = pContext->item->szName + _T(".") + szEncoderExtension.MakeLower();
    CString szOutputFile;
    if (szOutPath.GetLength() >= 1)
    {
        if (szOutPath[szOutPath.GetLength() - 1] == '\\' || szOutPath[szOutPath.GetLength() - 1] == '/')
            szOutputFile = szOutPath + szName;
        else
            szOutputFile = szOutPath + _T("\\") + szName;
    }
    else
    {
        szOutputFile = szName;
    }

    // processing mode
    Mode nProcessingMode = Mode::None;
    if (bIsValidEncoderInput)
        nProcessingMode = Mode::Encode;
    else
        nProcessingMode = Mode::Transcode;

    bool bDecode = false;
    int nTool = -1;
    bool bUseInPipesEnc = false;
    bool bUseOutPipesEnc = false;
    bool bUseInPipesDec = false;
    bool bUseOutPipesDec = false;
    CString szOrgInputFile = szInputFile;
    CString szOrgOutputFile = szOutputFile;

    // decode before encoding
    if (nProcessingMode == Mode::Transcode)
    {
        int nDecoder = pContext->pWorkerContext->pConfig->m_Formats.GetDecoderByExtension(pContext->item->szExtension);
        if (nDecoder == -1)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: can not find valid decoder by extension."));
            return bSuccess;
        }

        CFormat& decoderFormat = pContext->pWorkerContext->pConfig->m_Formats.GetData(nDecoder);
        CPreset& decoderPreset = decoderFormat.m_Presets.GetData(decoderFormat.nDefaultPreset);
        CString szDecoderExePath = decoderFormat.szPath;
        CString szDecoderOptions = decoderPreset.szOptions;

        bIsValidEncoderInput = encoderFormat.IsValidInputExtension(decoderFormat.szOutputExtension);
        if (bIsValidEncoderInput == false)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: decoder output not supported by encoder."));
            return bSuccess;
        }

        if (pContext->pWorkerContext->pConfig->m_Options.bForceConsoleWindow == false)
        {
            // configure decoder input and output pipes
            bUseInPipesDec = decoderFormat.bInput;
            bUseOutPipesDec = decoderFormat.bOutput;
        }

        // input file is stdin
        if (bUseInPipesDec == true)
            szInputFile = _T("-");

        // output file is stdout
        if (bUseOutPipesDec == true)
            szOutputFile = _T("-");

        // TODO: bUseOutPipes == true than handle szOutputFile same as input file
        if (nProcessingMode == Mode::Transcode)
        {
            CString szDecoderExtension = decoderFormat.szOutputExtension;
            szOutputFile = szOutputFile + +_T(".") + szDecoderExtension.MakeLower();
        }

        // build full command line for decoder (DECODER-EXE + OPTIONS + INFILE + OUTFILE)
        // this is basic model, some of encoder may have different command-line structure
        CString szExecute;
        szExecute = decoderFormat.szTemplate;
        szExecute.Replace(_T("$EXE"), _T("\"$EXE\""));
        szExecute.Replace(_T("$EXE"), szDecoderExePath);
        szExecute.Replace(_T("$OPTIONS"), szDecoderOptions);
        szExecute.Replace(_T("$INFILE"), _T("\"$INFILE\""));
        szExecute.Replace(_T("$INFILE"), szInputFile);
        szExecute.Replace(_T("$OUTFILE"), _T("\"$OUTFILE\""));
        szExecute.Replace(_T("$OUTFILE"), szOutputFile);

        bDecode = true;
        nTool = pContext->pWorkerContext->pConfig->m_Formats.GetFormatById(decoderFormat.szId);
        if (nTool == -1)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: failed to get decoder by format id."));
            return bSuccess;
        }

        lstrcpy(szCommandLine, szExecute.GetBuffer(szExecute.GetLength()));

        pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Decoding..."));

        CFileContext context;
        context.pWorkerContext = pContext->pWorkerContext;
        context.szInputFile = szOrgInputFile;
        context.szOutputFile = szOrgOutputFile;
        context.szCommandLine = szCommandLine;
        context.nIndex = pContext->item->nId;
        context.bDecode = bDecode;
        context.nTool = nTool;
        context.bUseReadPipes = bUseInPipesDec;
        context.bUseWritePipes = bUseOutPipesDec;

        // TODO: when transcoding don't show time stats
        bool bResult = false;
        try
        {
            bResult = ::ConvertFile(&context);
        }
        catch (...)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: exception thrown while decoding."));
            pContext->pWorkerContext->Callback(pContext->item->nId, -1, true, true);
        }

        if (bResult == true)
        {
            if (pContext->pWorkerContext->pConfig->m_Options.bDeleteSourceFiles == true)
                ::DeleteFile(szOrgInputFile);
        }
        else
        {
            if (pContext->pWorkerContext->pConfig->m_Options.bDeleteOnError == true)
                ::DeleteFile(szOutputFile);

            if (pContext->pWorkerContext->pConfig->m_Options.bStopOnErrors == true)
                return bSuccess;

            return bSuccess;
        }
    }

    if (pContext->pWorkerContext->bRunning == false)
        return bSuccess;

    if (pContext->pWorkerContext->pConfig->m_Options.bForceConsoleWindow == false)
    {
        // configure encoder input and output pipes
        bUseInPipesEnc = encoderFormat.bInput;
        bUseOutPipesEnc = encoderFormat.bOutput;
    }

    if (nProcessingMode == Mode::Encode)
    {
        // input file is stdin
        if (bUseInPipesEnc == true)
            szInputFile = _T("-");

        // output file is stdout
        if (bUseOutPipesEnc == true)
            szOutputFile = _T("-");
    }

    if (nProcessingMode == Mode::Transcode)
    {
        // input filename is decoded output filename
        szInputFile = szOutputFile;
        szOrgInputFile = szOutputFile;

        // restore output filename
        szOutputFile = szOrgOutputFile;

        // input file is stdin
        if (bUseInPipesEnc == true)
            szInputFile = _T("-");

        // output file is stdout
        if (bUseOutPipesEnc == true)
            szOutputFile = _T("-");
    }

    // encode
    if ((nProcessingMode == Mode::Encode) || (nProcessingMode == Mode::Transcode))
    {
        // build full command line for encoder (ENCODER-EXE + OPTIONS + INFILE + OUTFILE)
        // this is basic model, some of encoder may have different command-line structure
        CString szExecute;
        szExecute = encoderFormat.szTemplate;
        szExecute.Replace(_T("$EXE"), _T("\"$EXE\""));
        szExecute.Replace(_T("$EXE"), szEncoderExePath);
        szExecute.Replace(_T("$OPTIONS"), szEncoderOptions);
        szExecute.Replace(_T("$INFILE"), _T("\"$INFILE\""));
        szExecute.Replace(_T("$INFILE"), szInputFile);
        szExecute.Replace(_T("$OUTFILE"), _T("\"$OUTFILE\""));
        szExecute.Replace(_T("$OUTFILE"), szOutputFile);

        bDecode = false;
        nTool = pContext->pWorkerContext->pConfig->m_Formats.GetFormatById(encoderFormat.szId);
        if (nTool == -1)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: failed to get encoder by format id."));
            return bSuccess;
        }

        lstrcpy(szCommandLine, szExecute.GetBuffer(szExecute.GetLength()));

        pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Encoding..."));

        CFileContext context;
        context.pWorkerContext = pContext->pWorkerContext;
        context.szInputFile = szOrgInputFile;
        context.szOutputFile = szOrgOutputFile;
        context.szCommandLine = szCommandLine;
        context.nIndex = pContext->item->nId;
        context.bDecode = bDecode;
        context.nTool = nTool;
        context.bUseReadPipes = bUseInPipesEnc;
        context.bUseWritePipes = bUseOutPipesEnc;

        bool bResult = false;
        try
        {
            bResult = ::ConvertFile(&context);
        }
        catch (...)
        {
            pContext->pWorkerContext->Status(pContext->item->nId, _T("--:--"), _T("Error: exception thrown while encoding."));
            pContext->pWorkerContext->Callback(pContext->item->nId, -1, true, true);
        }

        if (bResult == true)
        {
            bSuccess = true;
            if (pContext->pWorkerContext->pConfig->m_Options.bDeleteSourceFiles == true)
                ::DeleteFile(szOrgInputFile);
        }
        else
        {
            if (pContext->pWorkerContext->pConfig->m_Options.bDeleteOnError == true)
                ::DeleteFile(szOutputFile);
        }

        if (nProcessingMode == Mode::Transcode)
            ::DeleteFile(szOrgInputFile);
    }

    return bSuccess;
}
<|endoftext|>