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.
This commit is contained in:
Benjamin Otte
2017-10-02 02:14:31 +02:00
parent a07924c0d6
commit e48be683c7
11 changed files with 286 additions and 26 deletions

View File

@@ -20,6 +20,7 @@
#define __GSK_H_INSIDE__
#include <gsk/gskcodesource.h>
#include <gsk/gskenums.h>
#include <gsk/gskpixelshader.h>
#include <gsk/gskrenderer.h>

151
gsk/gskcodesource.c Normal file
View File

@@ -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);
}

41
gsk/gskcodesource.h Normal file
View File

@@ -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__ */

View File

@@ -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__ */

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}
@@ -1393,18 +1425,6 @@ set_parse_error (GError **error,
va_end (args);
}
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,

View File

@@ -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);

View File

@@ -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;

View File

@@ -14,6 +14,7 @@ gsk_private_source_shaders = [
]
gsk_public_sources = files([
'gskcodesource.c',
'gskpixelshader.c',
'gskrenderer.c',
'gskrendernode.c',