<commit_before>/*!
 * \file gl_program.cpp
 * \brief file gl_program.cpp
 *
 * Adapted from: WRATHGLProgram.cpp of WRATH:
 *
 * Copyright 2013 by Nomovok Ltd.
 * Contact: <EMAIL>
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author <NAME> <<EMAIL>>
 * \author <NAME> <<EMAIL>>
 */


#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <set>
#include <string>
#include <map>
#include <vector>
#include <list>
#include <algorithm>
#include <sstream>
#include <stdint.h>
#include <boost/utility.hpp>


#include <fastuidraw/util/static_resource.hpp>
#include <fastuidraw/gl_backend/gl_program.hpp>

namespace
{
  class SourcePrivate
  {
  public:
    SourcePrivate();

    typedef enum fastuidraw::gl::Shader::shader_source_type source_type;
    typedef enum fastuidraw::gl::Shader::shader_extension_enable_type extension_enable_type;
    typedef std::pair<std::string, source_type> source_code_type;

    bool m_dirty;
    std::list<source_code_type> m_values;
    std::map<std::string, extension_enable_type> m_extensions;
    std::string m_version;

    std::string m_assembled_code;

    static
    std::string
    strip_leading_white_spaces(const std::string &S);

    static
    void
    emit_source_line(std::ostream &output_stream,
                     const std::string &source,
                     int line_number, const std::string &label);

    static
    void
    add_source_code_from_stream(const std::string &label,
                                std::istream &istr,
                                std::ostream &output_stream);

    static
    void
    add_source_entry(const source_code_type &v, std::ostream &output_stream);

    static
    const char*
    string_from_extension_type(extension_enable_type tp);
  };

  class ShaderPrivate
  {
  public:
    ShaderPrivate(const fastuidraw::gl::Shader::shader_source &src,
                  GLenum pshader_type);

    void
    compile(void);

    bool m_shader_ready;
    GLuint m_name;
    GLenum m_shader_type;

    std::string m_source_code;
    std::string m_compile_log;
    bool m_compile_success;
  };

  class BindAttributePrivate
  {
  public:
    BindAttributePrivate(const char *pname, int plocation):
      m_label(pname),
      m_location(plocation)
    {}

    std::string m_label;
    int m_location;
  };

  class PreLinkActionArrayPrivate
  {
  public:
    std::vector<fastuidraw::gl::PreLinkAction::handle> m_values;
  };

  class UniformBlockInitializerPrivate
  {
  public:
    UniformBlockInitializerPrivate(const char *n, int v):
      m_block_name(n),
      m_binding_point(v)
    {}

    std::string m_block_name;
    int m_binding_point;
  };

  class ProgramInitializerArrayPrivate
  {
  public:
    std::vector<fastuidraw::gl::ProgramInitializer::handle> m_values;
  };

  class ParameterInfoPrivate
  {
  public:
    ParameterInfoPrivate(void):
      m_name(""),
      m_type(GL_INVALID_ENUM),
      m_count(0),
      m_index(-1),
      m_location(-1)
    {}

    bool
    operator<(const ParameterInfoPrivate &rhs) const
    {
      return m_name < rhs.m_name;
    }

    std::string m_name;
    GLenum m_type;
    GLint m_count;
    GLuint m_index;
    GLint m_location;
  };

  typedef std::pair<int, const ParameterInfoPrivate*> FindParameterResult;

  class ParameterInfoPrivateHoard
  {
  public:

    FindParameterResult
    find_parameter(const std::string &pname);

    template<typename F, typename G>
    void
    fill_hoard(GLuint program,
               GLenum count_enum, GLenum length_enum,
               F fptr, G gptr);

    template<typename iterator>
    static
    std::string
    filter_name(iterator begin, iterator end, int &array_index);

    std::vector<ParameterInfoPrivate> m_values;
    std::map<std::string, int> m_map;
  };

  class ShaderData
  {
  public:
    std::string m_source_code;
    GLuint m_name;
    GLenum m_shader_type;
    std::string m_compile_log;
  };

  class ProgramPrivate
  {
  public:
    ProgramPrivate(const fastuidraw::const_c_array<fastuidraw::gl::Shader::handle> pshaders,
                   const fastuidraw::gl::PreLinkActionArray &action,
                   const fastuidraw::gl::ProgramInitializerArray &initers,
                   fastuidraw::gl::Program *p):
      m_shaders(pshaders.begin(), pshaders.end()),
      m_name(0),
      m_assembled(false),
      m_initializers(initers),
      m_pre_link_actions(action),
      m_p(p)
    {
    }

    ProgramPrivate(fastuidraw::gl::Shader::handle vert_shader,
                   fastuidraw::gl::Shader::handle frag_shader,
                   const fastuidraw::gl::PreLinkActionArray &action,
                   const fastuidraw::gl::ProgramInitializerArray &initers,
                   fastuidraw::gl::Program *p):
      m_name(0),
      m_assembled(false),
      m_initializers(initers),
      m_pre_link_actions(action),
      m_p(p)
    {
      m_shaders.push_back(vert_shader);
      m_shaders.push_back(frag_shader);
    }

    ProgramPrivate(const fastuidraw::gl::Shader::shader_source &vert_shader,
                   const fastuidraw::gl::Shader::shader_source &frag_shader,
                   const fastuidraw::gl::PreLinkActionArray &action,
                   const fastuidraw::gl::ProgramInitializerArray &initers,
                   fastuidraw::gl::Program *p):
      m_name(0),
      m_assembled(false),
      m_initializers(initers),
      m_pre_link_actions(action),
      m_p(p)
    {
      m_shaders.push_back(FASTUIDRAWnew fastuidraw::gl::Shader(vert_shader, GL_VERTEX_SHADER));
      m_shaders.push_back(FASTUIDRAWnew fastuidraw::gl::Shader(frag_shader, GL_FRAGMENT_SHADER));
    }

    void
    assemble(void);

    void
    clear_shaders_and_save_shader_data(void);

    void
    generate_log(void);

    std::vector<fastuidraw::gl::Shader::handle> m_shaders;
    std::vector<ShaderData> m_shader_data;
    std::map<GLenum, std::vector<int> > m_shader_data_sorted_by_type;

    GLuint m_name;
    bool m_link_success, m_assembled;
    std::string m_link_log;
    std::string m_log;

    std::set<std::string> m_binded_attributes;
    ParameterInfoPrivateHoard m_uniform_list;
    ParameterInfoPrivateHoard m_attribute_list;
    fastuidraw::gl::ProgramInitializerArray m_initializers;
    fastuidraw::gl::PreLinkActionArray m_pre_link_actions;
    fastuidraw::gl::Program *m_p;

  };
}

//////////////////////////////////////////////////
// SourcePrivate methods
SourcePrivate::
SourcePrivate(void):
  m_dirty(true),
#ifdef FASTUIDRAW_GL_USE_GLES
  m_version("300 es")
#else
  m_version("330")
#endif
{
}


const char*
SourcePrivate::
string_from_extension_type(enum fastuidraw::gl::Shader::shader_extension_enable_type tp)
{
  switch(tp)
    {
    case fastuidraw::gl::Shader::enable_extension:
      return "enable";
      break;

    case fastuidraw::gl::Shader::require_extension:
      return "require";
      break;

    case fastuidraw::gl::Shader::warn_extension:
      return "warn";
      break;

    case fastuidraw::gl::Shader::disable_extension:
      return "disable";
      break;

    default:
      assert(!"Unknown value for gl::Shader::shader_extension_enable_type");
      return "";
    }

}

std::string
SourcePrivate::
strip_leading_white_spaces(const std::string &S)
{
  std::string::const_iterator iter, end;
  for(iter = S.begin(), end = S.end(); iter != end and isspace(*iter); ++iter)
    {
    }
  return (iter != end and *iter == '#')?
    std::string(iter, end):
    S;
}

void
SourcePrivate::
emit_source_line(std::ostream &output_stream,
                 const std::string &source,
                 int line_number, const std::string &label)
{
  std::string S;
  S = strip_leading_white_spaces(source);
  output_stream << S;

  #ifndef NDEBUG
    {
      if(S.empty() || *S.rbegin() != '\\')
        {
          output_stream << std::setw(80-S.length()) << "  //LOCATION("
                        << std::setw(3) << line_number
                        << ", " << label
                        << ")";
        }
    }
  #endif

  output_stream << "\n";
}


void
SourcePrivate::
add_source_code_from_stream(const std::string &label,
                            std::istream &istr,
                            std::ostream &output_stream)
{
  std::string S;
  int line_number(1);

  while(getline(istr, S))
    {
      emit_source_line(output_stream, S, line_number, label);
      ++line_number;
      S.clear();
    }
}

void
SourcePrivate::
add_source_entry(const source_code_type &v, std::ostream &output_stream)
{
  if(v.second == fastuidraw::gl::Shader::from_file)
    {
      std::ifstream file(v.first.c_str());

      if(file)
        {
          add_source_code_from_stream(v.first, file, output_stream);
        }
      else
        {
          output_stream << "\n//WARNING: Could not open file \""
                        << v.first << "\"\n";
        }
    }
  else
    {
      std::istringstream istr;
      std::string label;

      if(v.second == fastuidraw::gl::Shader::from_string)
        {
          istr.str(v.first);
          label="raw string";
        }
      else
        {
          fastuidraw::const_c_array<uint8_t> resource_string;

          resource_string = fastuidraw::fetch_static_resource(v.first.c_str());
          label=v.first;
          if(!resource_string.empty() && resource_string.back() == 0)
            {
              const char *s;
              s = reinterpret_cast<const char*>(resource_string.c_ptr());
              istr.str(std::string(s));
            }
          else
            {
              output_stream << "\n//Unable to fetch string resource \"" << v.first
                            << "\"\n";
              return;
            }
        }
      add_source_code_from_stream(label, istr, output_stream);
    }
}


/////////////////////////////////////////
// ShaderPrivate methods<commit_msg>fastuidraw/gl_backend/gl_program: tweak/improve source location data<commit_after>/*!
 * \file gl_program.cpp
 * \brief file gl_program.cpp
 *
 * Adapted from: WRATHGLProgram.cpp of WRATH:
 *
 * Copyright 2013 by Nomovok Ltd.
 * Contact: <EMAIL>
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author <NAME> <<EMAIL>>
 * \author <NAME> <<EMAIL>>
 */


#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <set>
#include <string>
#include <map>
#include <vector>
#include <list>
#include <algorithm>
#include <sstream>
#include <stdint.h>
#include <boost/utility.hpp>


#include <fastuidraw/util/static_resource.hpp>
#include <fastuidraw/gl_backend/gl_program.hpp>

namespace
{
  class SourcePrivate
  {
  public:
    SourcePrivate();

    typedef enum fastuidraw::gl::Shader::shader_source_type source_type;
    typedef enum fastuidraw::gl::Shader::shader_extension_enable_type extension_enable_type;
    typedef std::pair<std::string, source_type> source_code_type;

    bool m_dirty;
    std::list<source_code_type> m_values;
    std::map<std::string, extension_enable_type> m_extensions;
    std::string m_version;

    std::string m_assembled_code;

    static
    std::string
    strip_leading_white_spaces(const std::string &S);

    static
    void
    emit_source_line(std::ostream &output_stream,
                     const std::string &source,
                     int line_number, const std::string &label);

    static
    void
    add_source_code_from_stream(const std::string &label,
                                std::istream &istr,
                                std::ostream &output_stream);

    static
    void
    add_source_entry(const source_code_type &v, std::ostream &output_stream);

    static
    const char*
    string_from_extension_type(extension_enable_type tp);
  };

  class ShaderPrivate
  {
  public:
    ShaderPrivate(const fastuidraw::gl::Shader::shader_source &src,
                  GLenum pshader_type);

    void
    compile(void);

    bool m_shader_ready;
    GLuint m_name;
    GLenum m_shader_type;

    std::string m_source_code;
    std::string m_compile_log;
    bool m_compile_success;
  };

  class BindAttributePrivate
  {
  public:
    BindAttributePrivate(const char *pname, int plocation):
      m_label(pname),
      m_location(plocation)
    {}

    std::string m_label;
    int m_location;
  };

  class PreLinkActionArrayPrivate
  {
  public:
    std::vector<fastuidraw::gl::PreLinkAction::handle> m_values;
  };

  class UniformBlockInitializerPrivate
  {
  public:
    UniformBlockInitializerPrivate(const char *n, int v):
      m_block_name(n),
      m_binding_point(v)
    {}

    std::string m_block_name;
    int m_binding_point;
  };

  class ProgramInitializerArrayPrivate
  {
  public:
    std::vector<fastuidraw::gl::ProgramInitializer::handle> m_values;
  };

  class ParameterInfoPrivate
  {
  public:
    ParameterInfoPrivate(void):
      m_name(""),
      m_type(GL_INVALID_ENUM),
      m_count(0),
      m_index(-1),
      m_location(-1)
    {}

    bool
    operator<(const ParameterInfoPrivate &rhs) const
    {
      return m_name < rhs.m_name;
    }

    std::string m_name;
    GLenum m_type;
    GLint m_count;
    GLuint m_index;
    GLint m_location;
  };

  typedef std::pair<int, const ParameterInfoPrivate*> FindParameterResult;

  class ParameterInfoPrivateHoard
  {
  public:

    FindParameterResult
    find_parameter(const std::string &pname);

    template<typename F, typename G>
    void
    fill_hoard(GLuint program,
               GLenum count_enum, GLenum length_enum,
               F fptr, G gptr);

    template<typename iterator>
    static
    std::string
    filter_name(iterator begin, iterator end, int &array_index);

    std::vector<ParameterInfoPrivate> m_values;
    std::map<std::string, int> m_map;
  };

  class ShaderData
  {
  public:
    std::string m_source_code;
    GLuint m_name;
    GLenum m_shader_type;
    std::string m_compile_log;
  };

  class ProgramPrivate
  {
  public:
    ProgramPrivate(const fastuidraw::const_c_array<fastuidraw::gl::Shader::handle> pshaders,
                   const fastuidraw::gl::PreLinkActionArray &action,
                   const fastuidraw::gl::ProgramInitializerArray &initers,
                   fastuidraw::gl::Program *p):
      m_shaders(pshaders.begin(), pshaders.end()),
      m_name(0),
      m_assembled(false),
      m_initializers(initers),
      m_pre_link_actions(action),
      m_p(p)
    {
    }

    ProgramPrivate(fastuidraw::gl::Shader::handle vert_shader,
                   fastuidraw::gl::Shader::handle frag_shader,
                   const fastuidraw::gl::PreLinkActionArray &action,
                   const fastuidraw::gl::ProgramInitializerArray &initers,
                   fastuidraw::gl::Program *p):
      m_name(0),
      m_assembled(false),
      m_initializers(initers),
      m_pre_link_actions(action),
      m_p(p)
    {
      m_shaders.push_back(vert_shader);
      m_shaders.push_back(frag_shader);
    }

    ProgramPrivate(const fastuidraw::gl::Shader::shader_source &vert_shader,
                   const fastuidraw::gl::Shader::shader_source &frag_shader,
                   const fastuidraw::gl::PreLinkActionArray &action,
                   const fastuidraw::gl::ProgramInitializerArray &initers,
                   fastuidraw::gl::Program *p):
      m_name(0),
      m_assembled(false),
      m_initializers(initers),
      m_pre_link_actions(action),
      m_p(p)
    {
      m_shaders.push_back(FASTUIDRAWnew fastuidraw::gl::Shader(vert_shader, GL_VERTEX_SHADER));
      m_shaders.push_back(FASTUIDRAWnew fastuidraw::gl::Shader(frag_shader, GL_FRAGMENT_SHADER));
    }

    void
    assemble(void);

    void
    clear_shaders_and_save_shader_data(void);

    void
    generate_log(void);

    std::vector<fastuidraw::gl::Shader::handle> m_shaders;
    std::vector<ShaderData> m_shader_data;
    std::map<GLenum, std::vector<int> > m_shader_data_sorted_by_type;

    GLuint m_name;
    bool m_link_success, m_assembled;
    std::string m_link_log;
    std::string m_log;

    std::set<std::string> m_binded_attributes;
    ParameterInfoPrivateHoard m_uniform_list;
    ParameterInfoPrivateHoard m_attribute_list;
    fastuidraw::gl::ProgramInitializerArray m_initializers;
    fastuidraw::gl::PreLinkActionArray m_pre_link_actions;
    fastuidraw::gl::Program *m_p;

  };
}

//////////////////////////////////////////////////
// SourcePrivate methods
SourcePrivate::
SourcePrivate(void):
  m_dirty(true),
#ifdef FASTUIDRAW_GL_USE_GLES
  m_version("300 es")
#else
  m_version("330")
#endif
{
}


const char*
SourcePrivate::
string_from_extension_type(enum fastuidraw::gl::Shader::shader_extension_enable_type tp)
{
  switch(tp)
    {
    case fastuidraw::gl::Shader::enable_extension:
      return "enable";
      break;

    case fastuidraw::gl::Shader::require_extension:
      return "require";
      break;

    case fastuidraw::gl::Shader::warn_extension:
      return "warn";
      break;

    case fastuidraw::gl::Shader::disable_extension:
      return "disable";
      break;

    default:
      assert(!"Unknown value for gl::Shader::shader_extension_enable_type");
      return "";
    }

}

std::string
SourcePrivate::
strip_leading_white_spaces(const std::string &S)
{
  std::string::const_iterator iter, end;
  for(iter = S.begin(), end = S.end(); iter != end and isspace(*iter); ++iter)
    {
    }
  return (iter != end and *iter == '#')?
    std::string(iter, end):
    S;
}

void
SourcePrivate::
emit_source_line(std::ostream &output_stream,
                 const std::string &source,
                 int line_number, const std::string &label)
{
  std::string S;
  S = strip_leading_white_spaces(source);
  output_stream << S;

  #ifndef NDEBUG
    {
      if(!label.empty() && (S.empty() || *S.rbegin() != '\\'))
        {
          output_stream << std::setw(80-S.length()) << "  //["
                        << std::setw(3) << line_number
                        << ", " << label
                        << "]";
        }
    }
  #else
    {
      FASTUIDRAWunused(label);
      FASTUIDRAWunused(line_number);
    }
  #endif

  output_stream << "\n";
}


void
SourcePrivate::
add_source_code_from_stream(const std::string &label,
                            std::istream &istr,
                            std::ostream &output_stream)
{
  std::string S;
  int line_number(1);

  while(getline(istr, S))
    {
      emit_source_line(output_stream, S, line_number, label);
      ++line_number;
      S.clear();
    }
}

void
SourcePrivate::
add_source_entry(const source_code_type &v, std::ostream &output_stream)
{
  if(v.second == fastuidraw::gl::Shader::from_file)
    {
      std::ifstream file(v.first.c_str());

      if(file)
        {
          add_source_code_from_stream(v.first, file, output_stream);
        }
      else
        {
          output_stream << "\n//WARNING: Could not open file \""
                        << v.first << "\"\n";
        }
    }
  else
    {
      std::istringstream istr;
      std::string label;

      if(v.second == fastuidraw::gl::Shader::from_string)
        {
          istr.str(v.first);
          label.clear();
        }
      else
        {
          fastuidraw::const_c_array<uint8_t> resource_string;

          resource_string = fastuidraw::fetch_static_resource(v.first.c_str());
          label=v.first;
          if(!resource_string.empty() && resource_string.back() == 0)
            {
              const char *s;
              s = reinterpret_cast<const char*>(resource_string.c_ptr());
              istr.str(std::string(s));
            }
          else
            {
              output_stream << "\n//Unable to fetch string resource \"" << v.first
                            << "\"\n";
              return;
            }
        }
      add_source_code_from_stream(label, istr, output_stream);
    }
}


/////////////////////////////////////////
// ShaderPrivate methods
{'fraction_non_alphanumeric': 0.12459194776931447, 'fraction_numerical': 0.0025719655752299933, 'mean_word_length': 2.6695099818511796, 'pattern_counts': {'":': 0, '<': 149, '<?xml version=': 0, '>': 85, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '238555', 'n_tokens_mistral': 6593, 'n_tokens_neox': 6439, 'n_words': 1169}