static gboolean read_reply_sync (GInputStream *input, DSIHeader *dsi_header, char **data, GCancellable *cancellable, GError **error) { gboolean res; gsize read_count, bytes_read; g_assert (dsi_header != NULL); read_count = sizeof (DSIHeader); res = g_input_stream_read_all (input, dsi_header, read_count, &bytes_read, cancellable, error); if (!res) return FALSE; if (bytes_read < read_count) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Connection unexpectedly went down")); return FALSE; } dsi_header->requestID = GUINT16_FROM_BE (dsi_header->requestID); dsi_header->errorCode = GUINT32_FROM_BE (dsi_header->errorCode); dsi_header->totalDataLength = GUINT32_FROM_BE (dsi_header->totalDataLength); if (dsi_header->totalDataLength == 0) { *data = NULL; return TRUE; } *data = g_malloc (dsi_header->totalDataLength); read_count = dsi_header->totalDataLength; res = g_input_stream_read_all (input, *data, read_count, &bytes_read, cancellable, error); if (!res) { g_free (*data); return FALSE; } if (bytes_read < read_count) { g_free (*data); g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Got EOS")); return FALSE; } return TRUE; }
static void _ghwp_file_v3_parse_styles (GHWPDocument *doc) { g_return_if_fail (doc != NULL); guint16 n_styles; guint8 *buffer = NULL; gsize bytes_read; GInputStream *stream = GHWP_FILE_V3 (doc->file)->priv->stream; g_input_stream_read_all (stream, &n_styles, 2, &bytes_read, NULL, NULL); buffer = g_malloc (n_styles * (20 + 31 + 187)); g_input_stream_read_all (stream, buffer, n_styles * (20 + 31 + 187), &bytes_read, NULL, NULL); g_free (buffer); }
static void _ghwp_file_v3_parse_font_names (GHWPDocument *doc) { g_return_if_fail (doc != NULL); guint16 n_fonts; int i = 0; guint8 *buffer = NULL; gsize bytes_read; GInputStream *stream = GHWP_FILE_V3 (doc->file)->priv->stream; for (i = 0; i < 7; i++) { g_input_stream_read_all (stream, &n_fonts, 2, &bytes_read, NULL, NULL); buffer = g_malloc (40 * n_fonts); g_input_stream_read_all (stream, buffer, 40 * n_fonts, &bytes_read, NULL, NULL); g_free (buffer); } }
static void read_file (GFile *scratch_file) { GInputStream *input_stream; GError *error = NULL; gint i; input_stream = (GInputStream *) g_file_read (scratch_file, NULL, &error); if (!input_stream) { g_printerr ("Failed to open scratch file: %s\n", error->message); return; } for (i = 0; i < FILE_SIZE; i += BUFFER_SIZE) { gchar buffer [BUFFER_SIZE]; gsize bytes_read; if (!g_input_stream_read_all (input_stream, buffer, BUFFER_SIZE, &bytes_read, NULL, &error) || bytes_read < BUFFER_SIZE) { g_printerr ("Failed to read back scratch file: %s\n", error->message); g_input_stream_close (input_stream, NULL, NULL); g_object_unref (input_stream); } } g_object_unref (input_stream); }
static VALUE rg_read_all(int argc, VALUE *argv, VALUE self) { VALUE rbcount, cancellable, result; gsize count; GError *error = NULL; gsize bytes_read; rb_scan_args(argc, argv, "11", &rbcount, &cancellable); count = RVAL2GSIZE(rbcount); result = rb_str_new(NULL, count); if (!g_input_stream_read_all(_SELF(self), RSTRING_PTR(result), count, &bytes_read, RVAL2GCANCELLABLE(cancellable), &error)) rbgio_raise_error(error); rb_str_set_len(result, bytes_read); rb_str_resize(result, bytes_read); OBJ_TAINT(result); return result; }
GList * gimp_palette_load_act (GimpContext *context, GFile *file, GInputStream *input, GError **error) { GimpPalette *palette; gchar *palette_name; guchar color_bytes[3]; gsize bytes_read; g_return_val_if_fail (G_IS_FILE (file), NULL); g_return_val_if_fail (G_IS_INPUT_STREAM (input), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); palette_name = g_path_get_basename (gimp_file_get_utf8_name (file)); palette = GIMP_PALETTE (gimp_palette_new (context, palette_name)); g_free (palette_name); while (g_input_stream_read_all (input, color_bytes, sizeof (color_bytes), &bytes_read, NULL, NULL) && bytes_read == sizeof (color_bytes)) { GimpRGB color; gimp_rgba_set_uchar (&color, color_bytes[0], color_bytes[1], color_bytes[2], 255); gimp_palette_add_entry (palette, -1, NULL, &color); } return g_list_prepend (NULL, palette); }
static gsize read_from_stream (GInputStream *stream, guchar **buffer, gsize size) { GError *error = NULL; gboolean success; gsize read; *buffer = g_try_new (guchar, size); g_assert (*buffer != NULL); success = g_input_stream_read_all (G_INPUT_STREAM (stream), (void *) *buffer, size, &read, NULL, &error); if (!success || error != NULL) { g_warning (error->message); g_error_free (error); return -1; } return read; }
gboolean _rpmostree_util_update_checksum_from_file (GChecksum *checksum, GFile *src, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; gsize bytes_read; char buf[4096]; gs_unref_object GInputStream *filein = NULL; filein = (GInputStream*)g_file_read (src, cancellable, error); if (!filein) goto out; do { if (!g_input_stream_read_all (filein, buf, sizeof(buf), &bytes_read, cancellable, error)) goto out; g_checksum_update (checksum, (guint8*)buf, bytes_read); } while (bytes_read > 0); ret = TRUE; out: return ret; }
static gchar *readall(const gchar *path, GError **error) { GFile *f = g_file_new_for_path(path); GFileInputStream *fis = NULL; GFileInfo *info; int len; gchar *ret = NULL; if (!(info = g_file_query_info(f, "standard::*", G_FILE_QUERY_INFO_NONE, NULL, error))) goto cleanup; len = g_file_info_get_size(info); ret = g_new0(gchar, len+1); if (!(fis = g_file_read(f, NULL, error))) goto cleanup; if (!g_input_stream_read_all(G_INPUT_STREAM(fis), ret, len, NULL, NULL, error)) goto cleanup; ret[len] = '\0'; *error = NULL; cleanup: if (*error) { g_free(ret); ret = NULL; } g_object_unref(f); if (fis) g_object_unref(fis); return ret; }
static gboolean gimp_curves_tool_settings_import (GimpImageMapTool *image_map_tool, GInputStream *input, GError **error) { GimpCurvesTool *tool = GIMP_CURVES_TOOL (image_map_tool); gchar header[64]; gsize bytes_read; if (! g_input_stream_read_all (input, header, sizeof (header), &bytes_read, NULL, error) || bytes_read != sizeof (header)) { g_prefix_error (error, _("Could not read header: ")); return FALSE; } g_seekable_seek (G_SEEKABLE (input), 0, G_SEEK_SET, NULL, NULL); if (g_str_has_prefix (header, "# GIMP Curves File\n")) return gimp_curves_config_load_cruft (tool->config, input, error); return GIMP_IMAGE_MAP_TOOL_CLASS (parent_class)->settings_import (image_map_tool, input, error); }
/** * seahorse_util_read_to_memory: * @input: Data to read. The #GInputStream is read till the end. * @len: Length of the data read (out) * * Reads data from the input stream and returns them as #guchar * * Returns: The string read from data. The returned string should be freed * with #g_free when no longer needed. **/ guchar* seahorse_util_read_to_memory (GInputStream *input, guint *len) { gsize size = 128; gchar *buffer, *text; gsize nread = 0; GString *string; GSeekable *seek; if (G_IS_SEEKABLE (input)) { seek = G_SEEKABLE (input); g_seekable_seek (seek, 0, SEEK_SET, NULL, NULL); } string = g_string_new (""); buffer = g_new (gchar, size); while (g_input_stream_read_all (input, buffer, size, &nread, NULL, NULL)) { string = g_string_append_len (string, buffer, nread); if (nread != size) break; } if (len) *len = string->len; text = g_string_free (string, FALSE); g_free (buffer); return (guchar*)text; }
static guint16 * read_file_to_buffer (const gchar *name, gsize count, GError *e) { GError *error = NULL; guint16 *depth = NULL; GFile *new_file = g_file_new_for_path (name); GFileInputStream *input_stream = g_file_read (new_file, NULL, &error); if (error != NULL) { g_debug ("ERROR: %s", error->message); } else { gsize bread = 0; depth = g_slice_alloc (count); g_input_stream_read_all ((GInputStream *) input_stream, depth, count, &bread, NULL, &error); if (error != NULL) { g_debug ("ERROR: %s", error->message); } } return depth; }
static void korva_upnp_file_server_on_wrote_chunk (SoupMessage *msg, gpointer user_data) { ServeData *data = (ServeData *) user_data; int chunk_size; char *file_buffer; GError *error = NULL; gsize bytes_read; soup_server_pause_message (data->server, msg); chunk_size = MIN (data->end - data->start + 1, G_MAXUINT16 + 1); if (chunk_size <= 0) { soup_message_body_complete (msg->response_body); soup_server_unpause_message (data->server, msg); return; } file_buffer = g_malloc0 (chunk_size); g_input_stream_read_all (data->stream, (void *) file_buffer, chunk_size, &bytes_read, NULL, &error); data->start += chunk_size; soup_message_body_append (msg->response_body, SOUP_MEMORY_TAKE, file_buffer, chunk_size); soup_server_unpause_message (data->server, msg); }
gboolean ot_gio_splice_update_checksum (GOutputStream *out, GInputStream *in, GChecksum *checksum, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; g_return_val_if_fail (out != NULL || checksum != NULL, FALSE); if (checksum != NULL) { gsize bytes_read, bytes_written; char buf[4096]; do { if (!g_input_stream_read_all (in, buf, sizeof(buf), &bytes_read, cancellable, error)) goto out; if (!ot_gio_write_update_checksum (out, buf, bytes_read, &bytes_written, checksum, cancellable, error)) goto out; } while (bytes_read > 0); } else { if (g_output_stream_splice (out, in, 0, cancellable, error) < 0) goto out; } ret = TRUE; out: return ret; }
void test_error_stream (void) { GError *error = NULL; GInputStream *stream; char buffer[4096]; gsize bytes_read; process = gcut_process_new(cuttest_echo_path, "-e", "XXX", NULL); stream = gcut_process_get_error_stream(process); cut_assert_not_null(stream); gcut_process_run(process, &error); gcut_assert_error(error); wait_exited(); g_input_stream_read_all(stream, buffer, sizeof(buffer), &bytes_read, NULL, &error); gcut_assert_error(error); cut_assert_equal_memory("XXX\n", 4, buffer, bytes_read); }
static gboolean dracut_supports_reproducible (GFile *root, gboolean *supported, GCancellable *cancellable, GError **error) { int pid, stdout[2]; if (pipe (stdout) < 0) { glnx_set_error_from_errno (error); return FALSE; } pid = fork (); if (pid < 0) { close (stdout[0]); close (stdout[1]); glnx_set_error_from_errno (error); return FALSE; } /* Check that --reproducible is present in the --help output. */ if (pid == 0) { int null; char *child_argv[] = { "dracut", "--help", NULL }; null = open ("/dev/null", O_RDWR); if (null < 0 || close (stdout[0]) < 0 || dup2 (stdout[1], 1) < 0 || dup2 (null, 0) < 0 || dup2 (null, 2) < 0) _exit (1); run_sync_in_root (root, "dracut", child_argv, NULL); _exit (1); } else { gsize read = 0; /* the dracut 0.43 --help output is about 8Kb, leave some room. */ const gsize buffer_size = 16384; g_autofree gchar *buffer = g_new (gchar, buffer_size); g_autoptr(GInputStream) in = g_unix_input_stream_new (stdout[0], TRUE); if (close (stdout[1]) < 0) { glnx_set_error_from_errno (error); return FALSE; } if (!g_input_stream_read_all (in, buffer, buffer_size, &read, cancellable, error)) return FALSE; *supported = g_strstr_len (buffer, read, "--reproducible") != NULL; return TRUE; } }
/** * seahorse_util_read_data_block: * @buf: A string buffer to write the data to. * @input: The input stream to read from. * @start: The start signature to look for. * @end: The end signature to look for. * * Breaks out one block of data (usually a key) * * Returns: The number of bytes copied. */ guint seahorse_util_read_data_block (GString *buf, GInputStream *input, const gchar *start, const gchar* end) { const gchar *t; guint copied = 0; gchar ch; gsize read; /* Look for the beginning */ t = start; while (g_input_stream_read_all (input, &ch, 1, &read, NULL, NULL) && read == 1) { /* Match next char */ if (*t == ch) t++; /* Did we find the whole string? */ if (!*t) { buf = g_string_append (buf, start); copied += strlen (start); break; } } /* Look for the end */ t = end; while (g_input_stream_read_all (input, &ch, 1, &read, NULL, NULL) && read == 1) { /* Match next char */ if (*t == ch) t++; buf = g_string_append_c (buf, ch); copied++; /* Did we find the whole string? */ if (!*t) break; } return copied; }
/* * et_picture_load_file_data: * @file: the GFile from which to load an image * @error: a #GError to provide information on errors, or %NULL to ignore * * Load an image from the supplied @file. * * Returns: an image on success, %NULL otherwise */ static Picture * et_picture_load_file_data (GFile *file, GError **error) { Picture *pic; gchar *buffer = NULL; gsize size; gsize bytes_read; GFileInfo *info; GFileInputStream *file_istream; info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, NULL, error); if (!info) { g_assert (error == NULL || *error != NULL); return NULL; } file_istream = g_file_read (file, NULL, error); if (!file_istream) { g_assert (error == NULL || *error != NULL); return NULL; } size = g_file_info_get_size (info); buffer = g_malloc (size); g_object_unref (info); if (!g_input_stream_read_all (G_INPUT_STREAM (file_istream), buffer, size, &bytes_read, NULL, error)) { g_free (buffer); g_debug ("Only %" G_GSIZE_FORMAT " bytes out of %" G_GSIZE_FORMAT " bytes of picture data were read", bytes_read, size); g_object_unref (file_istream); g_assert (error == NULL || *error != NULL); return NULL; } else { /* Image loaded. */ pic = Picture_Allocate(); pic->size = size; pic->data = (guchar *)buffer; g_object_unref (file_istream); g_assert (error == NULL || *error == NULL); return pic; } }
static void _hwp_hwp3_parser_parse_styles (HwpHWP3Parser *parser, HwpHWP3File *file, GError **error) { g_return_if_fail (HWP_IS_HWP3_FILE (file)); guint16 n_styles; gchar *buffer = NULL; gsize bytes_read; GInputStream *stream = HWP_HWP3_FILE (file)->priv->stream; g_input_stream_read_all (stream, &n_styles, 2, &bytes_read, NULL, error); for (guint16 i = 0; i < n_styles; i++) { buffer = g_malloc (20 + 31 + 187); g_input_stream_read_all (stream, buffer, 20 + 31 + 187, &bytes_read, NULL, error); gchar *stylename = g_convert (buffer, 20, "UTF-8", "JOHAB", NULL, NULL, error); g_free (buffer); g_free (stylename); } }
static char * read_string (GDataInputStream *in) { gsize len; char *str; len = g_data_input_stream_read_uint16 (in, NULL, NULL); str = g_malloc (len + 1); g_input_stream_read_all (G_INPUT_STREAM (in), str, len, &len, NULL, NULL); str[len] = 0; return str; }
static void _hwp_hwp3_parser_parse_font_names (HwpHWP3Parser *parser, HwpHWP3File *file, GError **error) { g_return_if_fail (HWP_IS_HWP3_FILE (file)); guint16 n_fonts; gchar *buffer = NULL; gsize bytes_read; GInputStream *stream = HWP_HWP3_FILE (file)->priv->stream; for (guint8 i = 0; i < 7; i++) { g_input_stream_read_all (stream, &n_fonts, 2, &bytes_read, NULL, NULL); buffer = g_malloc (40 * n_fonts); g_input_stream_read_all (stream, buffer, 40 * n_fonts, &bytes_read, NULL, NULL); gchar *fontname = g_convert (buffer, bytes_read, "UTF-8", "JOHAB", NULL, NULL, error); g_free (buffer); g_free (fontname); } }
GHWPFile *ghwp_file_new_from_filename (const gchar* filename, GError** error) { g_return_val_if_fail (filename != NULL, NULL); /* check signature */ static const guint8 const signature_ole[] = { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }; static const guint8 signature_v3[] = { /* HWP Document File V3.00 \x1a\1\2\3\4\5 */ 0x48, 0x57, 0x50, 0x20, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x56, 0x33, 0x2e, 0x30, 0x30, 0x20, 0x1a, 0x01, 0x02, 0x03, 0x04, 0x05 }; GFile *file = g_file_new_for_path (filename); GFileInputStream *stream = g_file_read(file, NULL, error); if (!stream) return NULL; gsize bytes_read = 0; guint8 *buffer = g_malloc0 (4096); g_input_stream_read_all (G_INPUT_STREAM(stream), buffer, 4096, &bytes_read, NULL, error); if ( memcmp(buffer, signature_ole, sizeof(signature_ole)) == 0) { /* hwp v5 */ g_free(buffer); g_object_unref(stream); return GHWP_FILE (ghwp_file_v5_new_from_filename (filename, error)); } else if ( memcmp(buffer, signature_v3, sizeof(signature_v3)) == 0) { /* hwp v3 */ g_free(buffer); g_object_unref(stream); return GHWP_FILE (ghwp_file_v3_new_from_filename (filename, error)); } else if (is_hwpml((gchar *) buffer, bytes_read)) { /* hwp ml */ g_free(buffer); g_object_unref(stream); return GHWP_FILE (ghwp_file_ml_new_from_filename (filename, error)); } else { /* invalid hwp file */ *error = g_error_new (ghwp_file_error_quark(), GHWP_FILE_ERROR_INVALID, "invalid hwp file"); g_free(buffer); g_object_unref(stream); return NULL; } }
static GIOStream * g_socks4a_proxy_connect (GProxy *proxy, GIOStream *io_stream, GProxyAddress *proxy_address, GCancellable *cancellable, GError **error) { GInputStream *in; GOutputStream *out; const gchar *hostname; guint16 port; const gchar *username; hostname = g_proxy_address_get_destination_hostname (proxy_address); port = g_proxy_address_get_destination_port (proxy_address); username = g_proxy_address_get_username (proxy_address); in = g_io_stream_get_input_stream (io_stream); out = g_io_stream_get_output_stream (io_stream); /* Send SOCKS4 connection request */ { guint8 msg[SOCKS4_CONN_MSG_LEN]; gint len; len = set_connect_msg (msg, hostname, port, username, error); if (len < 0) goto error; if (!g_output_stream_write_all (out, msg, len, NULL, cancellable, error)) goto error; } /* Read SOCKS4 response */ { guint8 data[SOCKS4_CONN_REP_LEN]; if (!g_input_stream_read_all (in, data, SOCKS4_CONN_REP_LEN, NULL, cancellable, error)) goto error; if (!parse_connect_reply (data, error)) goto error; } return g_object_ref (io_stream); error: return NULL; }
static void read_fn(png_structp png_ptr, png_bytep buffer, png_size_t length) { GError *err = NULL; GInputStream *stream = G_INPUT_STREAM(png_get_io_ptr(png_ptr)); gsize bytes_read = 0; g_assert(stream); g_input_stream_read_all(stream, buffer, length, &bytes_read, NULL, &err); if (err) { g_printerr("gegl:load-png %s: %s\n", __PRETTY_FUNCTION__, err->message); } }
gboolean byzanz_deserialize_header (GInputStream * stream, guint * width, guint * height, GCancellable * cancellable, GError ** error) { char result[strlen (IDENTIFICATION) + 1]; guint32 size[2]; guchar endian; g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE); g_return_val_if_fail (width != NULL, FALSE); g_return_val_if_fail (height != NULL, FALSE); if (!g_input_stream_read_all (stream, result, sizeof (result), NULL, cancellable, error)) return FALSE; if (strncmp (result, IDENTIFICATION, strlen (IDENTIFICATION)) != 0) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Not a Byzanz recording")); return FALSE; } endian = result[strlen (IDENTIFICATION)]; if (endian != byte_order_to_uchar ()) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Unsupported byte order")); return FALSE; } if (!g_input_stream_read_all (stream, &size, sizeof (size), NULL, cancellable, error)) return FALSE; *width = size[0]; *height = size[1]; return TRUE; }
/* Called by gpgme to read data */ static ssize_t input_read (void *handle, void *buffer, size_t size) { GInputStream* input = handle; GError *err = NULL; gsize nread; g_return_val_if_fail (G_IS_INPUT_STREAM (input), -1); if (!g_input_stream_read_all (input, buffer, size, &nread, NULL, &err)) return handle_gio_error (err); return nread; }
/** * tracker_read_text_from_stream: * @stream: input stream to read from * @max_bytes: max number of bytes to read from @stream * * Reads up to @max_bytes from @stream, and validates the read text as proper * UTF-8. * * If the input text is not UTF-8 it will also try to decode it based on the * current locale, or windows-1252, or UTF-16. * * Returns: newly-allocated NUL-terminated UTF-8 string with the read text. **/ gchar * tracker_read_text_from_stream (GInputStream *stream, gsize max_bytes) { GString *s = NULL; gsize n_bytes_remaining = max_bytes; g_return_val_if_fail (stream, NULL); g_return_val_if_fail (max_bytes > 0, NULL); /* Reading in chunks of BUFFER_SIZE * Loop is halted whenever one of this conditions is met: * a) Read bytes reached the maximum allowed (max_bytes) * b) No more bytes to read * c) Error reading * d) Stream has less than 3 bytes * e) Stream has a single line of BUFFER_SIZE bytes with no EOL */ while (n_bytes_remaining > 0) { gchar buf[BUFFER_SIZE]; GError *error = NULL; gsize n_bytes_read; /* Read bytes from stream */ if (!g_input_stream_read_all (stream, buf, MIN (BUFFER_SIZE, n_bytes_remaining), &n_bytes_read, NULL, &error)) { g_message ("Error reading from stream: '%s'", error->message); g_error_free (error); break; } /* Process read bytes, and halt loop if needed */ if (!process_chunk (buf, n_bytes_read, BUFFER_SIZE, &n_bytes_remaining, &s)) { break; } } /* Validate UTF-8 if something was read, and return it */ return s ? process_whole_string (s) : NULL; }
static gboolean input_stream_read_uint64_all(GInputStream *stream, guint64 *data, GCancellable *cancellable, GError **error) { guint64 tmp; gsize bytes_read; gboolean res; res = g_input_stream_read_all(stream, &tmp, sizeof(tmp), &bytes_read, cancellable, error); g_assert(bytes_read == sizeof(tmp)); *data = GUINT64_FROM_BE(tmp); return res; }
gboolean hwp_hwp3_parser_read (HwpHWP3Parser *parser, void *buffer, gsize count) { g_return_val_if_fail (parser != NULL, FALSE); gboolean is_success = FALSE; is_success = g_input_stream_read_all (parser->stream, buffer, count, &parser->bytes_read, NULL, NULL); if ((is_success == FALSE) || (parser->bytes_read == 0)) { g_input_stream_close (parser->stream, NULL, NULL); return FALSE; } return TRUE; }
gboolean hwp_hwp3_parser_read_uint8 (HwpHWP3Parser *parser, guint8 *i) { g_return_val_if_fail (parser != NULL, FALSE); gboolean is_success = FALSE; is_success = g_input_stream_read_all (parser->stream, i, 1, &parser->bytes_read, NULL, NULL); if ((is_success == FALSE) || (parser->bytes_read != 1)) { *i = 0; g_input_stream_close (parser->stream, NULL, NULL); return FALSE; } return TRUE; }