[gtk+/wip/otte/shader: 175/269] gsk: Add GskCodeSource



commit 337489cc02ee481063812abfd05918417009c048
Author: Benjamin Otte <otte redhat com>
Date:   Mon Oct 2 02:14:31 2017 +0200

    gsk: Add GskCodeSource
    
    This is basically the source format we use to represent source code.
    
    It can be created either from a file or from a GBytes, so we can use it
    to hold all data that can be provided by user input (#defines) or by
    actual files.

 gsk/gsk.h                      |    1 +
 gsk/gskcodesource.c            |  151 ++++++++++++++++++++++++++++++++++++++++
 gsk/gskcodesource.h            |   41 +++++++++++
 gsk/gskcodesourceprivate.h     |   35 +++++++++
 gsk/gskslcompiler.c            |   11 +++-
 gsk/gskslpreprocessor.c        |    6 +-
 gsk/gskslpreprocessorprivate.h |    2 +-
 gsk/gsksltokenizer.c           |   56 ++++++++++-----
 gsk/gsksltokenizerprivate.h    |    6 +-
 gsk/gsktypes.h                 |    2 +
 gsk/meson.build                |    1 +
 11 files changed, 286 insertions(+), 26 deletions(-)
---
diff --git a/gsk/gsk.h b/gsk/gsk.h
index 0b9cbd3..d4490fd 100644
--- a/gsk/gsk.h
+++ b/gsk/gsk.h
@@ -20,6 +20,7 @@
 
 #define __GSK_H_INSIDE__
 
+#include <gsk/gskcodesource.h>
 #include <gsk/gskenums.h>
 #include <gsk/gskpixelshader.h>
 #include <gsk/gskrenderer.h>
diff --git a/gsk/gskcodesource.c b/gsk/gskcodesource.c
new file mode 100644
index 0000000..155994f
--- /dev/null
+++ b/gsk/gskcodesource.c
@@ -0,0 +1,151 @@
+/* GTK - The GIMP Toolkit
+ *   
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gskcodesourceprivate.h"
+
+struct _GskCodeSource {
+  GObject parent_instance;
+
+  char *name;
+  GFile *file;
+
+  GBytes *bytes;
+};
+
+G_DEFINE_TYPE (GskCodeSource, gsk_code_source, G_TYPE_OBJECT)
+
+static void
+gsk_code_source_dispose (GObject *object)
+{
+  GskCodeSource *source = GSK_CODE_SOURCE (object);
+
+  g_free (source->name);
+  if (source->file)
+    g_object_unref (source->file);
+  if (source->bytes)
+    g_bytes_unref (source->bytes);
+
+  G_OBJECT_CLASS (gsk_code_source_parent_class)->dispose (object);
+}
+
+static void
+gsk_code_source_class_init (GskCodeSourceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = gsk_code_source_dispose;
+}
+
+static void
+gsk_code_source_init (GskCodeSource *source)
+{
+}
+
+const char *
+gsk_code_source_get_name (GskCodeSource *source)
+{
+  g_return_val_if_fail (GSK_IS_CODE_SOURCE (source), NULL);
+
+  return source->name;
+}
+
+GFile *
+gsk_code_source_get_file (GskCodeSource *source)
+{
+  g_return_val_if_fail (GSK_IS_CODE_SOURCE (source), NULL);
+
+  return source->file;
+}
+
+GskCodeSource *
+gsk_code_source_new_for_bytes (const char *name,
+                               GBytes     *data)
+{
+  GskCodeSource *result;
+
+  g_return_val_if_fail (name != NULL, NULL);
+  g_return_val_if_fail (data != NULL, NULL);
+
+  result = g_object_new (GSK_TYPE_CODE_SOURCE, NULL);
+
+  result->name = g_strdup (name);
+  result->bytes = g_bytes_ref (data);
+
+  return result;
+}
+
+static char *
+get_name_for_file (GFile *file)
+{
+  GFileInfo *info;
+  char *result;
+
+  info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, NULL, NULL);
+
+  if (info)
+    {
+      result = g_strdup (g_file_info_get_display_name (info));
+      g_object_unref (info);
+    }
+  else
+    {
+      result = g_strdup ("<broken file>");
+    }
+
+  return result;
+}
+
+GskCodeSource *
+gsk_code_source_new_for_file (GFile *file)
+{
+  GskCodeSource *result;
+
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+
+  result = g_object_new (GSK_TYPE_CODE_SOURCE, NULL);
+
+  result->file = g_object_ref (file);
+  result->name = get_name_for_file (file);
+
+  return result;
+}
+
+GBytes *
+gsk_code_source_load (GskCodeSource  *source,
+                      GError        **error)
+{
+  gchar *data;
+  gsize length;
+
+  if (source->bytes)
+    return g_bytes_ref (source->bytes);
+
+  g_return_val_if_fail (source->file, NULL);
+
+  if (!g_file_load_contents (source->file,
+                             NULL,
+                             &data, &length,
+                             NULL,
+                             error))
+    return NULL;
+
+  return g_bytes_new_take (data, length);
+}
+
diff --git a/gsk/gskcodesource.h b/gsk/gskcodesource.h
new file mode 100644
index 0000000..415ed95
--- /dev/null
+++ b/gsk/gskcodesource.h
@@ -0,0 +1,41 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GSK_CODE_SOURCE_H__
+#define __GSK_CODE_SOURCE_H__
+
+#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
+#error "Only <gsk/gsk.h> can be included directly."
+#endif
+
+#include <gsk/gsktypes.h>
+
+G_BEGIN_DECLS
+
+#define GSK_TYPE_CODE_SOURCE (gsk_code_source_get_type ())
+
+G_DECLARE_FINAL_TYPE (GskCodeSource, gsk_code_source, GSK, CODE_SOURCE, GObject)
+
+GDK_AVAILABLE_IN_3_92
+const char *            gsk_code_source_get_name                (GskCodeSource       *source);
+GDK_AVAILABLE_IN_3_92
+GFile *                 gsk_code_source_get_file                (GskCodeSource       *source);
+
+G_END_DECLS
+
+#endif /* __GSK_CODE_SOURCE_H__ */
diff --git a/gsk/gskcodesourceprivate.h b/gsk/gskcodesourceprivate.h
new file mode 100644
index 0000000..83baa21
--- /dev/null
+++ b/gsk/gskcodesourceprivate.h
@@ -0,0 +1,35 @@
+/* GTK - The GIMP Toolkit
+ *
+ * Copyright © 2017 Benjamin Otte <otte gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GSK_CODE_SOURCE_PRIVATE_H__
+#define __GSK_CODE_SOURCE_PRIVATE_H__
+
+#include "gsk/gskcodesource.h"
+
+G_BEGIN_DECLS
+
+GskCodeSource *         gsk_code_source_new_for_bytes           (const char             *name,
+                                                                 GBytes                 *data);
+GskCodeSource *         gsk_code_source_new_for_file            (GFile                  *file);
+
+GBytes *                gsk_code_source_load                    (GskCodeSource          *source,
+                                                                 GError                **error);
+
+G_END_DECLS
+
+#endif /* __GSK_CODE_SOURCE_PRIVATE_H__ */
diff --git a/gsk/gskslcompiler.c b/gsk/gskslcompiler.c
index b473cec..1c0b9c6 100644
--- a/gsk/gskslcompiler.c
+++ b/gsk/gskslcompiler.c
@@ -20,6 +20,7 @@
 
 #include "gskslcompilerprivate.h"
 
+#include "gskcodesourceprivate.h"
 #include "gsksldefineprivate.h"
 #include "gskslpreprocessorprivate.h"
 #include "gskslprogramprivate.h"
@@ -101,6 +102,7 @@ gsk_sl_compiler_add_define (GskSlCompiler  *compiler,
   GskCodeLocation location;
   GskSlToken token = { 0, };
   GError *real_error = NULL;
+  GskCodeSource *source;
   GBytes *bytes;
 
   g_return_val_if_fail (GSK_IS_SL_COMPILER (compiler), FALSE);
@@ -118,7 +120,8 @@ gsk_sl_compiler_add_define (GskSlCompiler  *compiler,
 
   define = gsk_sl_define_new (name, NULL);
   bytes = g_bytes_new_static (definition, strlen (definition));
-  tokenizer = gsk_sl_tokenizer_new (bytes,
+  source = gsk_code_source_new_for_bytes ("<define>", bytes);
+  tokenizer = gsk_sl_tokenizer_new (source,
                                     gsk_sl_compiler_add_define_error_func,
                                     &real_error,
                                     NULL);
@@ -142,6 +145,7 @@ gsk_sl_compiler_add_define (GskSlCompiler  *compiler,
   gsk_sl_token_clear (&token);
   gsk_sl_tokenizer_unref (tokenizer);
   g_bytes_unref (bytes);
+  g_object_unref (source);
 
   if (real_error == NULL)
     {
@@ -187,12 +191,14 @@ gsk_sl_compiler_copy_defines (GskSlCompiler *compiler)
 
 GskSlProgram *
 gsk_sl_compiler_compile (GskSlCompiler *compiler,
-                         GBytes        *source)
+                         GBytes        *bytes)
 {
   GskSlPreprocessor *preproc;
+  GskCodeSource *source;
   GskSlProgram *program;
 
   program = g_object_new (GSK_TYPE_SL_PROGRAM, NULL);
+  source = gsk_code_source_new_for_bytes ("<program>", bytes);
 
   preproc = gsk_sl_preprocessor_new (compiler, source);
 
@@ -205,6 +211,7 @@ gsk_sl_compiler_compile (GskSlCompiler *compiler,
     }
 
   gsk_sl_preprocessor_unref (preproc);
+  g_object_unref (source);
 
   return program;
 }
diff --git a/gsk/gskslpreprocessor.c b/gsk/gskslpreprocessor.c
index eb22aaa..de92b69 100644
--- a/gsk/gskslpreprocessor.c
+++ b/gsk/gskslpreprocessor.c
@@ -20,6 +20,7 @@
 
 #include "gskslpreprocessorprivate.h"
 
+#include "gskcodesource.h"
 #include "gskslcompilerprivate.h"
 #include "gsksldefineprivate.h"
 #include "gsksltokenizerprivate.h"
@@ -75,7 +76,7 @@ gsk_sl_preprocessor_clear_token (gpointer data)
 
 GskSlPreprocessor *
 gsk_sl_preprocessor_new (GskSlCompiler *compiler,
-                         GBytes        *source)
+                         GskCodeSource *source)
 {
   GskSlPreprocessor *preproc;
 
@@ -609,7 +610,8 @@ gsk_sl_preprocessor_emit_error (GskSlPreprocessor     *preproc,
 {
   preproc->fatal_error |= fatal;
 
-  g_printerr ("%3zu:%2zu: %s: %s\n",
+  g_printerr ("%s:%zu:%zu: %s: %s\n",
+              gsk_code_source_get_name (location->source),
               location->lines + 1, location->line_bytes,
               fatal ? "error" : "warn",
               error->message);
diff --git a/gsk/gskslpreprocessorprivate.h b/gsk/gskslpreprocessorprivate.h
index 13755d1..3ea5939 100644
--- a/gsk/gskslpreprocessorprivate.h
+++ b/gsk/gskslpreprocessorprivate.h
@@ -26,7 +26,7 @@
 G_BEGIN_DECLS
 
 GskSlPreprocessor *     gsk_sl_preprocessor_new                 (GskSlCompiler       *compiler,
-                                                                 GBytes              *source);
+                                                                 GskCodeSource       *source);
 
 GskSlPreprocessor *     gsk_sl_preprocessor_ref                 (GskSlPreprocessor   *preproc);
 void                    gsk_sl_preprocessor_unref               (GskSlPreprocessor   *preproc);
diff --git a/gsk/gsksltokenizer.c b/gsk/gsksltokenizer.c
index ae3c5e5..220e3ad 100644
--- a/gsk/gsksltokenizer.c
+++ b/gsk/gsksltokenizer.c
@@ -20,6 +20,7 @@
 #include "gsksltokenizerprivate.h"
 
 #include "gskslcompiler.h"
+#include "gskcodesourceprivate.h"
 
 #include <math.h>
 #include <string.h>
@@ -36,6 +37,7 @@ struct _GskSlTokenReader {
 struct _GskSlTokenizer
 {
   gint                   ref_count;
+  GskCodeSource         *source;
   GBytes                *bytes;
   GskSlTokenizerErrorFunc error_func;
   gpointer               user_data;
@@ -45,9 +47,10 @@ struct _GskSlTokenizer
 };
 
 static void
-gsk_code_location_init (GskCodeLocation *location)
+gsk_code_location_init (GskCodeLocation *location,
+                        GskCodeSource   *source)
 {
-  memset (location, 0, sizeof (GskCodeLocation));
+  *location = (GskCodeLocation) { source, };
 }
 
 static void
@@ -1196,12 +1199,13 @@ gsk_sl_token_init_number (GskSlToken     *token,
 
 static void
 gsk_sl_token_reader_init (GskSlTokenReader *reader,
+                          GskCodeSource    *source,
                           GBytes           *bytes)
 {
   reader->data = g_bytes_get_data (bytes, NULL);
   reader->end = reader->data + g_bytes_get_size (bytes);
 
-  gsk_code_location_init (&reader->position);
+  gsk_code_location_init (&reader->position, source);
 }
 
 static void
@@ -1321,22 +1325,48 @@ gsk_sl_token_reader_consume (GskSlTokenReader *reader,
   reader->data += offset;
 }
 
+static void
+gsk_sl_tokenizer_emit_error (GskSlTokenizer        *tokenizer,
+                             const GskCodeLocation *location,
+                             const GskSlToken      *token,
+                             const GError          *error)
+{
+  if (tokenizer->error_func)
+    tokenizer->error_func (tokenizer, TRUE, location, token, error, tokenizer->user_data);
+  else
+    g_warning ("Unhandled GLSL error: %zu:%zu: %s", location->lines + 1, location->line_chars + 1, 
error->message);
+}
+
 GskSlTokenizer *
-gsk_sl_tokenizer_new (GBytes                  *bytes,
+gsk_sl_tokenizer_new (GskCodeSource           *source,
                       GskSlTokenizerErrorFunc  func,
                       gpointer                 user_data,
                       GDestroyNotify           user_destroy)
 {
   GskSlTokenizer *tokenizer;
+  GError *error = NULL;
 
   tokenizer = g_slice_new0 (GskSlTokenizer);
   tokenizer->ref_count = 1;
-  tokenizer->bytes = g_bytes_ref (bytes);
+  tokenizer->source = g_object_ref (source);
   tokenizer->error_func = func;
   tokenizer->user_data = user_data;
   tokenizer->user_destroy = user_destroy;
 
-  gsk_sl_token_reader_init (&tokenizer->reader, bytes);
+  tokenizer->bytes = gsk_code_source_load (source, &error);
+  if (tokenizer->bytes == NULL)
+    {
+      GskCodeLocation location;
+      GskSlToken token;
+
+      gsk_code_location_init (&location, tokenizer->source);
+      gsk_sl_token_init (&token, GSK_SL_TOKEN_EOF);
+      gsk_sl_tokenizer_emit_error (tokenizer, &location, &token, error);
+      g_error_free (error);
+      tokenizer->bytes = g_bytes_new (NULL, 0);
+    }
+
+  gsk_sl_token_reader_init (&tokenizer->reader, source, tokenizer->bytes);
 
   return tokenizer;
 }
@@ -1360,6 +1390,8 @@ gsk_sl_tokenizer_unref (GskSlTokenizer *tokenizer)
     tokenizer->user_destroy (tokenizer->user_data);
 
   g_bytes_unref (tokenizer->bytes);
+  g_object_unref (tokenizer->source);
+
   g_slice_free (GskSlTokenizer, tokenizer);
 }
 
@@ -1394,18 +1426,6 @@ set_parse_error (GError     **error,
 }
 
 static void
-gsk_sl_tokenizer_emit_error (GskSlTokenizer        *tokenizer,
-                             const GskCodeLocation *location,
-                             const GskSlToken      *token,
-                             const GError          *error)
-{
-  if (tokenizer->error_func)
-    tokenizer->error_func (tokenizer, TRUE, location, token, error, tokenizer->user_data);
-  else
-    g_warning ("Unhandled GLSL error: %zu:%zu: %s", location->lines + 1, location->line_chars + 1, 
error->message);
-}
-
-static void
 gsk_sl_token_reader_read_multi_line_comment (GskSlTokenReader  *reader,
                                              GskSlToken        *token,
                                              GError           **error)
diff --git a/gsk/gsksltokenizerprivate.h b/gsk/gsksltokenizerprivate.h
index 381a851..897e5aa 100644
--- a/gsk/gsksltokenizerprivate.h
+++ b/gsk/gsksltokenizerprivate.h
@@ -284,10 +284,10 @@ void                    gsk_sl_token_print                      (const GskSlToke
                                                                  GString               *string);
 char *                  gsk_sl_token_to_string                  (const GskSlToken      *token);
 
-GskSlTokenizer *        gsk_sl_tokenizer_new                    (GBytes                 *bytes,
+GskSlTokenizer *        gsk_sl_tokenizer_new                    (GskCodeSource         *source,
                                                                  GskSlTokenizerErrorFunc func,
-                                                                 gpointer                user_data,
-                                                                 GDestroyNotify          user_destroy);
+                                                                 gpointer               user_data,
+                                                                 GDestroyNotify         user_destroy);
 
 GskSlTokenizer *        gsk_sl_tokenizer_ref                    (GskSlTokenizer        *tokenizer);
 void                    gsk_sl_tokenizer_unref                  (GskSlTokenizer        *tokenizer);
diff --git a/gsk/gsktypes.h b/gsk/gsktypes.h
index 7323b93..613781a 100644
--- a/gsk/gsktypes.h
+++ b/gsk/gsktypes.h
@@ -27,6 +27,7 @@
 #include <gsk/gskenums.h>
 
 typedef struct _GskCodeLocation         GskCodeLocation;
+typedef struct _GskCodeSource           GskCodeSource;
 typedef struct _GskPixelShader          GskPixelShader;
 typedef struct _GskRenderer             GskRenderer;
 typedef struct _GskSlCompiler           GskSlCompiler;
@@ -35,6 +36,7 @@ typedef struct _GskTexture              GskTexture;
 
 struct _GskCodeLocation
 {
+  GskCodeSource         *source;
   gsize                  bytes;
   gsize                  chars;
   gsize                  lines;
diff --git a/gsk/meson.build b/gsk/meson.build
index fd3ffbe..0bb7a1f 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -14,6 +14,7 @@ gsk_private_source_shaders = [
 ]
 
 gsk_public_sources = files([
+  'gskcodesource.c',
   'gskpixelshader.c',
   'gskrenderer.c',
   'gskrendernode.c',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]