17 new revisions:
Revision: 56ad1138a3cf
Author: Marc Noirot <
marc....@gmail.com>
Date: Tue Apr 17 13:57:38 2012
Log: Removed reference to mjson.
http://code.google.com/p/flvmeta/source/detail?r=56ad1138a3cf
Revision: b5a8697f86ff
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 02:40:24 2012
Log: Fixed source archive generation to exclude any potential build
directo...
http://code.google.com/p/flvmeta/source/detail?r=b5a8697f86ff
Revision: cd8ab124de15
Author: Marc Noirot <
marc....@gmail.com>
Date: Tue Apr 17 13:58:52 2012
Log: Simple concept of a JSON emitter.
http://code.google.com/p/flvmeta/source/detail?r=cd8ab124de15
Revision: 89b2f867f02d
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 07:53:46 2012
Log: Completed the simple JSON emitter.
http://code.google.com/p/flvmeta/source/detail?r=89b2f867f02d
Revision: d53ec465f52e
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 08:02:12 2012
Log: Merged feature/simple_json.
http://code.google.com/p/flvmeta/source/detail?r=d53ec465f52e
Revision: f2aa9dae1f6a
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 08:04:28 2012
Log: Removed man page reference to mjson.
http://code.google.com/p/flvmeta/source/detail?r=f2aa9dae1f6a
Revision: f818fc9f6bb5
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 07:57:24 2012
Log: Added missing static function modifiers.
http://code.google.com/p/flvmeta/source/detail?r=f818fc9f6bb5
Revision: e1d582d9f528
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 08:42:22 2012
Log: Refactored the file dumping process so memory leaks are easier to
avoi...
http://code.google.com/p/flvmeta/source/detail?r=e1d582d9f528
Revision: 8434bd423217
Author: Marc Noirot <
marc....@gmail.com>
Date: Tue May 1 13:10:40 2012
Log: Fixed JSON dumping to prevent potential invalid output.
http://code.google.com/p/flvmeta/source/detail?r=8434bd423217
Revision: bfa013b67fd5
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 03:45:24 2012
Log: Improved current git commit detection.
http://code.google.com/p/flvmeta/source/detail?r=bfa013b67fd5
Revision: 986d26cfaff9
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 03:49:12 2012
Log: Moved cmake module to dedicated directory.
http://code.google.com/p/flvmeta/source/detail?r=986d26cfaff9
Revision: e0fa50c387da
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 03:53:24 2012
Log: Updated module search path.
http://code.google.com/p/flvmeta/source/detail?r=e0fa50c387da
Revision: 7e0e09067efc
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 03:54:03 2012
Log: Set version to 1.1.0.
http://code.google.com/p/flvmeta/source/detail?r=7e0e09067efc
Revision: c7d3a475cb83
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 05:51:22 2012
Log: Fixed Makefile.am to point to the correct path to
FindLibYaml.cmake.
http://code.google.com/p/flvmeta/source/detail?r=c7d3a475cb83
Revision: 27ca03eb73f5
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 07:55:51 2012
Log: Added a github README.md file.
http://code.google.com/p/flvmeta/source/detail?r=27ca03eb73f5
Revision: 6cd0e7aa7f9b
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 07:56:29 2012
Log: Updated documentation.
http://code.google.com/p/flvmeta/source/detail?r=6cd0e7aa7f9b
Revision: cf2a65bd80a1
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 08:05:20 2012
Log: Renamed FindLibYAML.cmake to better reflect project name.
http://code.google.com/p/flvmeta/source/detail?r=cf2a65bd80a1
==============================================================================
Revision: 56ad1138a3cf
Author: Marc Noirot <
marc....@gmail.com>
Date: Tue Apr 17 13:57:38 2012
Log: Removed reference to mjson.
http://code.google.com/p/flvmeta/source/detail?r=56ad1138a3cf
Modified:
/README
=======================================
--- /README Mon Sep 20 07:59:24 2010
+++ /README Tue Apr 17 13:57:38 2012
@@ -19,7 +19,6 @@
FLVmeta is fast (only bound by I/O speed) and has a very small memory
footprint.
The FLVmeta source package includes and uses the following software:
-- the mjson JSON document parser and emitter
(
http://mjson.sourceforge.net/)
- the libyaml YAML parser and emitter (
http://pyyaml.org/wiki/LibYAML)
==============================================================================
Revision: b5a8697f86ff
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 02:40:24 2012
Log: Fixed source archive generation to exclude any potential build
directory.
http://code.google.com/p/flvmeta/source/detail?r=b5a8697f86ff
Modified:
/CMakeLists.txt
=======================================
--- /CMakeLists.txt Sun Apr 29 09:37:44 2012
+++ /CMakeLists.txt Mon Apr 30 02:40:24 2012
@@ -109,7 +109,7 @@
set(CPACK_PACKAGE_VERSION ${FLVMETA_VERSION})
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/COPYING)
set(CPACK_RESOURCE_FILE_README ${CMAKE_SOURCE_DIR}/README)
-set(CPACK_SOURCE_IGNORE_FILES "/build.*;/CVS/;/\\\\.svn/;/\\\\.bzr/;/\\\\.hg/;/\\\\.git/;\\\\.swp$;\\\\.#;/#")
+set(CPACK_SOURCE_IGNORE_FILES "/*build*;/CVS/;/\\\\.svn/;/\\\\.bzr/;/\\\\.hg/;/\\\\.git/;\\\\.swp$;\\\\.#;/#")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "flvmeta-${PACKAGE_VERSION}-src")
if(WIN32)
==============================================================================
Revision: cd8ab124de15
Author: Marc Noirot <
marc....@gmail.com>
Date: Tue Apr 17 13:58:52 2012
Log: Simple concept of a JSON emitter.
http://code.google.com/p/flvmeta/source/detail?r=cd8ab124de15
Modified:
/src/json.c
/src/json.h
=======================================
--- /src/json.c Mon Jun 27 08:07:21 2011
+++ /src/json.c Tue Apr 17 13:58:52 2012
@@ -1,4211 +1,63 @@
-/***************************************************************************
- * Copyright (C) 2007 by Rui Maciel *
- *
rui.m...@gmail.com *
- *
*
- * This program is free software; you can redistribute it and/or modify
*
- * it under the terms of the GNU Library General Public License as
*
- * published by the Free Software Foundation; either version 2 of the
*
- * License, or (at your option) any later version.
*
- *
*
- * This program 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 Library General Public
*
- * License along with this program; if not, write to the
*
- * Free Software Foundation, Inc.,
*
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
-
***************************************************************************/
-
-#include "json.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <memory.h>
-
-
-enum LEX_VALUE
-{ LEX_MORE = 0,
- LEX_INVALID_CHARACTER,
- LEX_TRUE,
- LEX_FALSE,
- LEX_NULL,
- LEX_BEGIN_OBJECT,
- LEX_END_OBJECT,
- LEX_BEGIN_ARRAY,
- LEX_END_ARRAY,
- LEX_NAME_SEPARATOR,
- LEX_VALUE_SEPARATOR,
- LEX_STRING,
- LEX_NUMBER,
- LEX_ERROR,
- LEX_MEMORY
-};
-
-
-/* rc_string part */
-
-#define RSTRING_INCSTEP 5
-#define RSTRING_DEFAULT 8
-
-
-enum rui_string_error_codes
-{ RS_MEMORY, RS_OK = 1, RS_UNKNOWN };
-
-typedef enum rui_string_error_codes rstring_code;
-
-
-rcstring *
-rcs_create (size_t length)
-{
- rcstring *rcs;
- rcs = malloc (sizeof (rcstring)); /* allocates memory for a struct
rcstring */
- if (rcs == NULL)
- return NULL;
-
- rcs->max = length;
- rcs->length = 0;
-
- rcs->text = malloc ((rcs->max + 1) * sizeof (char));
- if (rcs->text == NULL)
- {
- free (rcs);
- return NULL;
- }
- rcs->text[0] = '\0';
-
- return rcs;
+/*
+ $Id: json.c 231 2011-06-27 13:46:19Z marc.noirot $
+
+ FLV Metadata updater
+
+ Copyright (C) 2007-2012 Marc Noirot <marc.noirot AT
gmail.com>
+
+ This file is part of FLVMeta.
+
+ FLVMeta 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 2 of the License, or
+ (at your option) any later version.
+
+ FLVMeta 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 FLVMeta; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
+*/
+
+#include <stdio.h>
+#include "json.h"
+
+void json_emit_init(json_emitter * je) {
+ je->comma_level = 0;
+ je->object_level = 0;
}
-
-void
-rcs_free (rcstring ** rcs)
-{
- assert (rcs != NULL);
- if (*rcs != NULL)
- {
- if ((*rcs)->text != NULL)
- {
- free ((*rcs)->text);
- (*rcs)->text = NULL;
- }
- free (*rcs);
- *rcs = NULL;
- }
-
+void json_emit_object_start(json_emitter * je) {
+ if (je->comma_level > 0) {
+ printf(",");
+ --je->comma_level;
+ }
+ printf("{");
+ ++je->object_level;
}
-
-rstring_code
-rcs_resize (rcstring * rcs, size_t length)
-{
- char *temp;
- assert (rcs != NULL);
-
- temp = realloc (rcs->text, sizeof (char) * (length + 1)); /* length
plus '\0' */
- if (temp == NULL)
- {
- free (rcs);
- return RS_MEMORY;
- }
- rcs->text = temp;
- rcs->max = length;
- rcs->text[rcs->max] = '\0';
- return RS_OK;
+void json_emit_object_end(json_emitter * je) {
+ printf("}");
+ --je->object_level;
}
-
-rstring_code
-rcs_catcs (rcstring * pre, const char *pos, const size_t length)
-{
- assert (pre != NULL);
- assert (pos != NULL);
-
- if (pre->max < pre->length + length)
- {
- if (rcs_resize (pre, pre->length + length + RSTRING_INCSTEP) != RS_OK)
- return RS_MEMORY;
- }
- strncpy (pre->text + pre->length, pos, length);
- pre->text[pre->length + length] = '\0';
- pre->length += length;
- return RS_OK;
+void json_emit_array_start(json_emitter * je) {
}
-
-rstring_code
-rcs_catc (rcstring * pre, const char c)
-{
- assert (pre != NULL);
-
- if (pre->max <= pre->length)
- {
- if (rcs_resize (pre, pre->max + RSTRING_INCSTEP) != RS_OK)
- return RS_MEMORY;
- }
- pre->text[pre->length] = c;
- pre->length++;
- pre->text[pre->length] = '\0';
- return RS_OK;
+void json_emit_array_end(json_emitter * je) {
}
-
-char *
-rcs_unwrap (rcstring * rcs)
-{
- char *out;
- assert (rcs != NULL);
-
- if (rcs->text == NULL)
- out = NULL;
- else
- {
- out = realloc (rcs->text, sizeof (char) * (strlen (rcs->text) + 1));
- }
-
- free (rcs);
- return out;
+void json_emit_boolean(json_emitter * je, byte value) {
}
-
-
-size_t
-rcs_length (rcstring * rcs)
-{
- /*TODO account for UTF8 */
- assert (rcs != NULL);
- return rcs->length;
+void json_emit_null(json_emitter * je) {
}
-
-/* end of rc_string part */
-
-
-enum json_error
-json_stream_parse (FILE * file, json_t ** document)
-{
- char buffer[1024]; /* hard-coded value */
- unsigned int error = JSON_INCOMPLETE_DOCUMENT;
-
- struct json_parsing_info state;
-
- assert (file != NULL); /* must be an open stream */
- assert (document != NULL); /* must be a valid pointer reference */
- assert (*document == NULL); /* only accepts a null json_t pointer, to
avoid memory leaks */
-
- json_jpi_init (&state); /* initializes the json_parsing_info object */
-
- while ((error == JSON_WAITING_FOR_EOF) || (error ==
JSON_INCOMPLETE_DOCUMENT))
- {
- if (fgets (buffer, 1024, file) != NULL)
- {
- switch (error = json_parse_fragment (&state, buffer))
- {
- case JSON_OK:
- case JSON_WAITING_FOR_EOF:
- case JSON_INCOMPLETE_DOCUMENT:
- break;
-
- default:
- json_free_value (&state.cursor);
- return error;
- break;
- }
- }
- else
- {
- if (error == JSON_WAITING_FOR_EOF)
- error = JSON_OK;
- else
- {
- /*TODO refine this error code */
- error = JSON_UNKNOWN_PROBLEM;
- }
- }
- }
-
- if (error == JSON_OK)
- {
- *document = state.cursor;
- }
-
- return error;
+void json_emit_number(json_emitter * je, number64 value) {
}
-
-json_t *
-json_new_value (const enum json_value_type type)
-{
- json_t *new_object;
- /* allocate memory to the new object */
- new_object = malloc (sizeof (json_t));
- if (new_object == NULL)
- return NULL;
-
- /* initialize members */
- new_object->text = NULL;
- new_object->parent = NULL;
- new_object->child = NULL;
- new_object->child_end = NULL;
- new_object->previous = NULL;
- new_object->next = NULL;
- new_object->type = type;
- return new_object;
-}
-
-
-json_t *
-json_new_string (const char *text)
-{
- json_t *new_object;
- size_t length;
-
- assert (text != NULL);
-
- /* allocate memory for the new object */
- new_object = malloc (sizeof (json_t));
- if (new_object == NULL)
- return NULL;
-
- /* initialize members */
- length = strlen (text) + 1;
- new_object->text = malloc (length * sizeof (char));
- if (new_object->text == NULL)
- {
- free (new_object);
- return NULL;
- }
- strncpy (new_object->text, text, length);
- new_object->parent = NULL;
- new_object->child = NULL;
- new_object->child_end = NULL;
- new_object->previous = NULL;
- new_object->next = NULL;
- new_object->type = JSON_STRING;
- return new_object;
-}
-
-
-json_t *
-json_new_number (const char *text)
-{
- json_t *new_object;
- size_t length;
-
- assert (text != NULL);
-
- /* allocate memory for the new object */
- new_object = malloc (sizeof (json_t));
- if (new_object == NULL)
- return NULL;
-
- /* initialize members */
- length = strlen (text) + 1;
- new_object->text = malloc (length * sizeof (char));
- if (new_object->text == NULL)
- {
- free (new_object);
- return NULL;
- }
- strncpy (new_object->text, text, length);
- new_object->parent = NULL;
- new_object->child = NULL;
- new_object->child_end = NULL;
- new_object->previous = NULL;
- new_object->next = NULL;
- new_object->type = JSON_NUMBER;
- return new_object;
-}
-
-
-json_t *
-json_new_object (void)
-{
- return json_new_value (JSON_OBJECT);
-}
-
-
-json_t *
-json_new_array (void)
-{
- return json_new_value (JSON_ARRAY);
-}
-
-
-json_t *
-json_new_null (void)
-{
- return json_new_value (JSON_NULL);
-}
-
-
-json_t *
-json_new_true (void)
-{
- return json_new_value (JSON_TRUE);
-}
-
-
-json_t *
-json_new_false (void)
-{
- return json_new_value (JSON_FALSE);
-}
-
-
-static void
-intern_json_free_value (json_t ** value)
-{
- assert (value != NULL);
- assert ((*value) != NULL);
- assert ((*value)->child == NULL);
-
- /* fixing sibling linked list connections */
- if ((*value)->previous && (*value)->next)
- {
- (*value)->previous->next = (*value)->next;
- (*value)->next->previous = (*value)->previous;
- }
- else
- {
- if ((*value)->previous)
- {
- (*value)->previous->next = NULL;
- }
- if ((*value)->next)
- {
- (*value)->next->previous = NULL;
- }
- }
-
- /*fixing parent node connections */
- if ((*value)->parent)
- {
- /* fix the tree connection to the first node in the children's list */
- if ((*value)->parent->child == (*value))
- {
- if ((*value)->next)
- {
- (*value)->parent->child = (*value)->next; /* the parent node always
points to the first node in the children linked list */
- }
- else
- {
- (*value)->parent->child = NULL;
- }
- }
-
- /* fix the tree connection to the last node in the children's list */
- if ((*value)->parent->child_end == (*value))
- {
- if ((*value)->previous)
- {
- (*value)->parent->child_end = (*value)->previous; /* the parent node
always points to the last node in the children linked list */
- }
- else
- {
- (*value)->parent->child_end = NULL;
- }
- }
- }
-
- /*finally, freeing the memory allocated for this value */
- if ((*value)->text != NULL)
- {
- free ((*value)->text);
- }
- free (*value); /* the json value */
- (*value) = NULL;
-}
-
-
-void
-json_free_value (json_t ** value)
-{
- json_t *cursor = *value;
-
- assert (value);
- assert (*value);
-
- while (*value)
- {
- json_t *parent;
-
- if (cursor->child)
- {
- cursor = cursor->child;
- continue;
- }
-
- if (cursor == *value)
- {
- *value = NULL;
- }
-
- parent = cursor->parent;
- intern_json_free_value (&cursor);
- cursor = parent;
- }
-}
-
-
-enum json_error
-json_insert_child (json_t * parent, json_t * child)
-{
- /*TODO change the child list from FIFO to LIFO, in order to get rid of
the child_end pointer */
- assert (parent != NULL); /* the parent must exist */
- assert (child != NULL); /* the child must exist */
- assert (parent != child); /* parent and child must not be the same. if
they are, it will enter an infinite loop */
-
- /* enforce tree structure correctness */
- switch (parent->type)
- {
- case JSON_STRING:
- /* a string accepts every JSON type as a child value */
- /* therefore, the sanity check must be performed on the child node */
- switch (child->type)
- {
- case JSON_STRING:
- case JSON_NUMBER:
- case JSON_TRUE:
- case JSON_FALSE:
- case JSON_NULL:
- if (child->child != NULL)
- return JSON_BAD_TREE_STRUCTURE;
- break;
-
- case JSON_OBJECT:
- case JSON_ARRAY:
- break;
-
- default:
- return JSON_BAD_TREE_STRUCTURE; /* this part should never be reached */
- break;
- }
- break;
-
- case JSON_OBJECT: /* JSON objects may only accept JSON string objects
which already have child nodes of their own */
- if (child->type != JSON_STRING)
- return JSON_BAD_TREE_STRUCTURE;
- break;
-
- case JSON_ARRAY:
- switch (child->type)
- {
- case JSON_STRING:
- case JSON_TRUE:
- case JSON_FALSE:
- case JSON_NULL:
- case JSON_NUMBER:
- if (child->child)
- return JSON_BAD_TREE_STRUCTURE;
- break;
-
- case JSON_OBJECT:
- case JSON_ARRAY:
- break;
-
- default:
- return JSON_BAD_TREE_STRUCTURE;
- }
- break;
-
- default:
- return JSON_BAD_TREE_STRUCTURE;
- }
-
- child->parent = parent;
- if (parent->child)
- {
- child->previous = parent->child_end;
- parent->child_end->next = child;
- parent->child_end = child;
- }
- else
- {
- parent->child = child;
- parent->child_end = child;
- }
-
- return JSON_OK;
-}
-
-
-enum json_error
-json_insert_pair_into_object (json_t * parent, const char *text_label,
json_t * value)
-{
- enum json_error error;
- json_t *label;
-
- /* verify if the parameters are valid */
- assert (parent != NULL);
- assert (text_label != NULL);
- assert (value != NULL);
- assert (parent != value);
-
- /* enforce type coherence */
- assert (parent->type == JSON_OBJECT);
-
-
- /* create label json_value */
- label = json_new_string (text_label);
- if (label == NULL)
- return JSON_MEMORY;
-
- /*insert value and check for error */
- error = json_insert_child (label, value);
- if (error != JSON_OK)
- return error;
- /*insert value and check for error */
- error = json_insert_child (parent, label);
- if (error != JSON_OK)
- return error;
-
- return JSON_OK;
-}
-
-
-enum json_error
-json_tree_to_string (json_t * root, char **text)
-{
- json_t *cursor;
- rcstring *output;
-
- assert (root != NULL);
- assert (text != NULL);
-
- cursor = root;
- /* set up the output and temporary rwstrings */
- output = rcs_create (RSTRING_DEFAULT);
-
- /* start the convoluted fun */
- state1: /* open value */
- {
- if ((cursor->previous) && (cursor != root)) /*if cursor is children and
not root than it is a followup sibling */
- {
- /* append comma */
- if (rcs_catc (output, ',') != RS_OK)
- {
- return JSON_MEMORY;
- }
- }
- switch (cursor->type)
- {
- case JSON_STRING:
- /* append the "text"\0, which means 1 + wcslen(cursor->text) + 1 + 1 */
- /* set the new output size */
- if (rcs_catc (output, '\"') != RS_OK)
- {
- return JSON_MEMORY;
- }
- if (rcs_catcs (output, cursor->text, strlen (cursor->text)) != RS_OK)
- {
- return JSON_MEMORY;
- }
- if (rcs_catc (output, '\"') != RS_OK)
- {
- return JSON_MEMORY;
- }
-
- if (cursor->parent != NULL)
- {
- if (cursor->parent->type == JSON_OBJECT) /* cursor is label in
label:value pair */
- {
- /* error checking: if parent is object and cursor is string then
cursor must have a single child */
- if (cursor->child != NULL)
- {
- if (rcs_catc (output, ':') != RS_OK)
- {
- return JSON_MEMORY;
- }
- }
- else
- {
- /* malformed document tree: label without value in label:value pair
*/
- rcs_free (&output);
- text = NULL;
- return JSON_BAD_TREE_STRUCTURE;
- }
- }
- }
- else /* does not have a parent */
- {
- if (cursor->child != NULL) /* is root label in label:value pair */
- {
- if (rcs_catc (output, ':') != RS_OK)
- {
- return JSON_MEMORY;
- }
- }
- else
- {
- /* malformed document tree: label without value in label:value pair */
- rcs_free (&output);
- text = NULL;
- return JSON_BAD_TREE_STRUCTURE;
- }
- }
- break;
-
- case JSON_NUMBER:
- /* must not have any children */
- /* set the new size */
- if (rcs_catcs (output, cursor->text, strlen (cursor->text)) != RS_OK)
- {
- return JSON_MEMORY;
- }
- goto state2; /* close value */
- break;
-
- case JSON_OBJECT:
- if (rcs_catc (output, '{') != RS_OK)
- {
- return JSON_MEMORY;
- }
-
- if (cursor->child)
- {
- cursor = cursor->child;
- goto state1; /* open value */
- }
- else
- {
- goto state2; /* close value */
- }
- break;
-
- case JSON_ARRAY:
- if (rcs_catc (output, '[') != RS_OK)
- {
- return JSON_MEMORY;
- }
-
- if (cursor->child != NULL)
- {
- cursor = cursor->child;
- goto state1;
- }
- else
- {
- goto state2; /* close value */
- }
- break;
-
- case JSON_TRUE:
- /* must not have any children */
- if (rcs_catcs (output, "true", 4) != RS_OK)
- {
- return JSON_MEMORY;
- }
- goto state2; /* close value */
- break;
-
- case JSON_FALSE:
- /* must not have any children */
- if (rcs_catcs (output, "false", 5) != RS_OK)
- {
- return JSON_MEMORY;
- }
- goto state2; /* close value */
- break;
-
- case JSON_NULL:
- /* must not have any children */
- if (rcs_catcs (output, "null", 4) != RS_OK)
- {
- return JSON_MEMORY;
- }
- goto state2; /* close value */
- break;
-
- default:
- goto error;
- }
- if (cursor->child)
- {
- cursor = cursor->child;
- goto state1; /* open value */
- }
- else
- {
- /* does not have any children */
- goto state2; /* close value */
- }
- }
-
- state2: /* close value */
- {
- switch (cursor->type)
- {
- case JSON_OBJECT:
- if (rcs_catc (output, '}') != RS_OK)
- {
- return JSON_MEMORY;
- }
- break;
-
- case JSON_ARRAY:
- if (rcs_catc (output, ']') != RS_OK)
- {
- return JSON_MEMORY;
- }
- break;
-
- case JSON_STRING:
- break;
- case JSON_NUMBER:
- break;
- case JSON_TRUE:
- break;
- case JSON_FALSE:
- break;
- case JSON_NULL:
- break;
- default:
- goto error;
- }
- if ((cursor->parent == NULL) || (cursor == root))
- {
- goto end;
- }
- else if (cursor->next)
- {
- cursor = cursor->next;
- goto state1; /* open value */
- }
- else
- {
- cursor = cursor->parent;
- goto state2; /* close value */
- }
- }
-
- error:
- {
- rcs_free (&output);
- return JSON_UNKNOWN_PROBLEM;
- }
-
- end:
- {
- *text = rcs_unwrap (output);
- return JSON_OK;
- }
-}
-
-
-enum json_error
-json_stream_output (FILE * file, json_t * root)
-{
- json_t *cursor;
-
- assert (root != NULL);
- assert (file != NULL); /* the file stream must be opened */
-
- cursor = root;
- /* set up the output and temporary rwstrings */
-
- /* start the convoluted fun */
- state1: /* open value */
- {
- if ((cursor->previous) && (cursor != root)) /*if cursor is children and
not root than it is a followup sibling */
- {
- /* append comma */
- fprintf (file, ",");
- }
- switch (cursor->type)
- {
- case JSON_STRING:
- /* append the "text"\0, which means 1 + wcslen(cursor->text) + 1 + 1 */
- /* set the new output size */
- fprintf (file, "\"%s\"", cursor->text);
-
- if (cursor->parent != NULL)
- {
- if (cursor->parent->type == JSON_OBJECT) /* cursor is label in
label:value pair */
- {
- /* error checking: if parent is object and cursor is string then
cursor must have a single child */
- if (cursor->child != NULL)
- {
- if (fprintf (file, ":") != RS_OK)
- {
- return JSON_MEMORY;
- }
- }
- else
- {
- /* malformed document tree: label without value in label:value pair
*/
- return JSON_BAD_TREE_STRUCTURE;
- }
- }
- }
- else /* does not have a parent */
- {
- if (cursor->child != NULL) /* is root label in label:value pair */
- {
- fprintf (file, ":");
- }
- else
- {
- /* malformed document tree: label without value in label:value pair */
- return JSON_BAD_TREE_STRUCTURE;
- }
- }
- break;
-
- case JSON_NUMBER:
- /* must not have any children */
- /* set the new size */
- fprintf (file, "%s", cursor->text);
- goto state2; /* close value */
- break;
-
- case JSON_OBJECT:
- fprintf (file, "{");
-
- if (cursor->child)
- {
- cursor = cursor->child;
- goto state1; /* open value */
- }
- else
- {
- goto state2; /* close value */
- }
- break;
-
- case JSON_ARRAY:
- fprintf (file, "[");
-
- if (cursor->child != NULL)
- {
- cursor = cursor->child;
- goto state1;
- }
- else
- {
- goto state2; /* close value */
- }
- break;
-
- case JSON_TRUE:
- /* must not have any children */
- fprintf (file, "true");
- goto state2; /* close value */
- break;
-
- case JSON_FALSE:
- /* must not have any children */
- fprintf (file, "false");
- goto state2; /* close value */
- break;
-
- case JSON_NULL:
- /* must not have any children */
- fprintf (file, "null");
- goto state2; /* close value */
- break;
-
- default:
- goto error;
- }
- if (cursor->child)
- {
- cursor = cursor->child;
- goto state1; /* open value */
- }
- else
- {
- /* does not have any children */
- goto state2; /* close value */
- }
- }
-
- state2: /* close value */
- {
- switch (cursor->type)
- {
- case JSON_OBJECT:
- fprintf (file, "}");
- break;
-
- case JSON_ARRAY:
- fprintf (file, "]");
- break;
-
- case JSON_STRING:
- break;
- case JSON_NUMBER:
- break;
- case JSON_TRUE:
- break;
- case JSON_FALSE:
- break;
- case JSON_NULL:
- break;
- default:
- goto error;
- }
- if ((cursor->parent == NULL) || (cursor == root))
- {
- goto end;
- }
***The diff for this file has been truncated for email.***
=======================================
--- /src/json.h Mon Jun 27 07:07:36 2011
+++ /src/json.h Tue Apr 17 13:58:52 2012
@@ -1,340 +1,69 @@
-/***************************************************************************
- * Copyright (C) 2007 by Rui Maciel *
- *
rui.m...@gmail.com *
- *
*
- * This program is free software; you can redistribute it and/or modify
*
- * it under the terms of the GNU Library General Public License as
*
- * published by the Free Software Foundation; either version 2 of the
*
- * License, or (at your option) any later version.
*
- *
*
- * This program 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 Library General Public
*
- * License along with this program; if not, write to the
*
- * Free Software Foundation, Inc.,
*
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
-
***************************************************************************/
-
-/** @file json.h A small library that helps deal with JSON-encoded
information
-\ingroup JSON
-
-\note error handling is only in a very rudimentary form.
-\author Rui Maciel
rui_m...@users.sourceforge.net
-\author Sven Herzberg
-\version v1.2
-*/
-
-#ifndef JSON_H
-#define JSON_H
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#define JSON_MAX_STRING_LENGTH SIZE_MAX-1
+/*
+ $Id: json.h 231 2011-06-27 13:46:19Z marc.noirot $
+
+ FLV Metadata updater
+
+ Copyright (C) 2007-2012 Marc Noirot <marc.noirot AT
gmail.com>
+
+ This file is part of FLVMeta.
+
+ FLVMeta 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 2 of the License, or
+ (at your option) any later version.
+
+ FLVMeta 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 FLVMeta; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
+*/
+
+#ifndef __JSON_H__
+#define __JSON_H__
+
+#include "types.h"
/**
-The descriptions of the json_value node type
-**/
- enum json_value_type
- { JSON_STRING = 0, JSON_NUMBER, JSON_OBJECT, JSON_ARRAY, JSON_TRUE,
JSON_FALSE, JSON_NULL };
-
-/**
-String implementation
-**/
- struct rui_cstring
- {
- char *text; /*<! char c-string */
- size_t length; /*<! put in place to avoid strlen() calls */
- size_t max; /*<! usable memory allocated to text minus the space for the
nul character */
- };
-
- typedef struct rui_cstring rcstring;
-
-/**
-The error messages produced by the JSON parsers
-**/
- enum json_error
- {
- JSON_OK = 1, /*!< everything went smoothly */
- JSON_INCOMPLETE_DOCUMENT, /*!< the parsed document didn't ended */
- JSON_WAITING_FOR_EOF, /*!< A complete JSON document tree was already
finished but needs to get to EOF. Other characters beyond whitespaces
produce errors */
- JSON_MALFORMED_DOCUMENT, /* the JSON document which was fed to this
parser is malformed */
- JSON_INCOMPATIBLE_TYPE, /*!< the currently parsed type does not belong
here */
- JSON_MEMORY, /*!< an error occurred when allocating memory */
- JSON_ILLEGAL_CHARACTER, /*!< the currently parsed character does not
belong here */
- JSON_BAD_TREE_STRUCTURE, /*!< the document tree structure is malformed */
- JSON_MAXIMUM_LENGTH, /*!< the parsed string reached the maximum allowed
size */
- JSON_UNKNOWN_PROBLEM /*!< some random, unaccounted problem occurred */
- };
-
-
-/**
-The JSON document tree node, which is a basic JSON type
-**/
- typedef struct json_value
- {
- enum json_value_type type; /*!< the type of node */
- char *text; /*!< The text stored by the node. It stores UTF-8 strings
and is used exclusively by the JSON_STRING and JSON_NUMBER node types */
-
- /* FIFO queue data */
- struct json_value *next; /*!< The pointer pointing to the next element
in the FIFO sibling list */
- struct json_value *previous; /*!< The pointer pointing to the previous
element in the FIFO sibling list */
- struct json_value *parent; /*!< The pointer pointing to the parent node
in the document tree */
- struct json_value *child; /*!< The pointer pointing to the first child
node in the document tree */
- struct json_value *child_end; /*!< The pointer pointing to the last
child node in the document tree */
- } json_t;
-
-
-/**
-The structure holding all information needed to resume parsing
-**/
- struct json_parsing_info
- {
- unsigned int state; /*!< the state where the parsing was left on the
last parser run */
- unsigned int lex_state;
- rcstring *lex_text;
- char *p;
- int string_length_limit_reached; /*!< flag informing if the string limit
length defined by JSON_MAX_STRING_LENGTH was reached */
- json_t *cursor; /*!< pointers to nodes belonging to the document tree
which aid the document parsing */
- };
-
-
-/**
-The structure which holds the pointers to the functions that will be
called by the saxy parser whenever their evens are triggered
-**/
- struct json_saxy_functions
- {
- int (*open_object) ();
- int (*close_object) ();
- int (*open_array) ();
- int (*close_array) ();
- int (*new_string) (char *text);
- int (*new_number) (char *text);
- int (*new_true) ();
- int (*new_false) ();
- int (*new_null) ();
- int (*label_value_separator) ();
- int (*sibling_separator) ();
- };
-
-
-/**
-The structure holding the information needed for json_saxy_parse to resume
parsing
-**/
- struct json_saxy_parser_status
- {
- unsigned int state; /*!< current parser state */
- int string_length_limit_reached; /*!< flag informing if the string limit
length defined by JSON_MAX_STRING_LENGTH was reached */
- rcstring *temp; /*!< temporary string which will be used to build up
parsed strings between parser runs. */
- };
-
-
-/**
-Buils a json_t document by parsing an open file
-@param file a pointer to an object controlling a stream, returned by
fopen()
-@param document a reference to a json_t pointer, set to NULL, which will
store the parsed document
-@return a json_error error code according to how the parsing operation
went.
-**/
- enum json_error json_stream_parse (FILE * file, json_t ** document);
-
-
-/**
-Creates a new JSON value and defines it's type
-@param type the value's type
-@return a pointer to the newly created value structure
-**/
- json_t *json_new_value (const enum json_value_type type);
-
-
-/**
-Creates a new JSON string and defines it's text
-@param text the value's text
-@return a pointer to the newly created JSON string value
-**/
- json_t *json_new_string (const char *text);
-
-
-/**
-Creates a new JSON number and defines it's text. The user is responsible
for the number string's correctness
-@param text the value's number
-@return a pointer to the newly created JSON string value
-**/
- json_t *json_new_number (const char *text);
-
-
-/**
-Creates a new JSON object
-@return a pointer to the newly created JSON object value
-**/
- json_t *json_new_object (void);
-
-
-/**
-Creates a new JSON array
-@return a pointer to the newly created JSON array value
-**/
- json_t *json_new_array (void);
-
-
-/**
-Creates a new JSON null
-@return a pointer to the newly created JSON null value
-**/
- json_t *json_new_null (void);
-
-
-/**
-Creates a new JSON true
-@return a pointer to the newly created JSON true value
-**/
- json_t *json_new_true (void);
-
-
-/**
-Creates a new JSON false
-@return a pointer to the newly created JSON false value
-**/
- json_t *json_new_false (void);
-
-
-/**
-Frees the memory appointed to the value fed as the parameter, as well as
all the child nodes
-@param value the root node of the tree being freed
-**/
- void json_free_value (json_t ** value);
-
-
-/**
-Inserts a child node into a parent node, as well as performs some document
tree integrity checks.
-@param parent the parent node
-@param child the node being added as a child to parent
-@return the error code corresponding to the operation result
-**/
- enum json_error json_insert_child (json_t * parent, json_t * child);
-
-
-/**
-Inserts a label:value pair into a parent node, as well as performs some
document tree integrity checks.
-@param parent the parent node
-@param text_label a char string which serves as the label in the
label:value pair
-@param value the value in the label:value pair
-@return the error code corresponding to the operation result
-**/
- enum json_error json_insert_pair_into_object (json_t * parent, const char
*text_label, json_t * value);
-
-
-/**
-Produces a JSON markup text document from a document tree
-@param root The document's root node
-@param text a pointer to a char string that will hold the JSON document
text.
-@return a json_error code describing how the operation went
-**/
- enum json_error json_tree_to_string (json_t * root, char **text);
-
-
-/**
-Produces a JSON markup text document from a json_t document tree to a text
stream
-@param file a opened file stream
-@param root The document's root node
-@return a json_error code describing how the operation went
-**/
- enum json_error json_stream_output (FILE * file, json_t * root);
-
-
-/**
-Strips all JSON white spaces from the text string
-@param text a char string holding a JSON document or document snippet
-**/
- void json_strip_white_spaces (char *text);
-
-
-/**
-Formats a JSON markup text contained in the given string
-@param text a JSON formatted document
-@return a pointer to a char string holding the formated document
-**/
- char *json_format_string (const char *text);
-
-
-/**
-Outputs a new UTF8 c-string which replaces all characters that must be
escaped with their respective escaped versions
-@param text an UTF8 char text string
-@return an UTF-8 c-string holding the same text string but with escaped
characters
-**/
- char *json_escape (char *text);
-
-/**
- * Outputs a new UTF-8 c-string which has all escaped characters replaced
by
- * their unescaped, UTF-8 encoded variants.
- *
- * @param test a UTF-8 c-string
- * @return a newly allocated UTF-8 c-string; free with free()
- */
- char *json_unescape (char *text);
-
-
-/**
-This function takes care of the tedious task of initializing any instance
of
-struct json_parsing_info
-@param jpi a pointer to a struct json_parsing_info instance
-**/
- void json_jpi_init (struct json_parsing_info *jpi);
-
-
-/**
-Produces a document tree sequentially from a JSON markup text fragment
-@param info the information necessary to resume parsing any incomplete
document
-@param buffer a null-terminated c-string containing a JSON document
fragment
-@return a code describing how the operation ended up
-**/
- enum json_error json_parse_fragment (struct json_parsing_info *info, char
*buffer);
-
-
-/**
-Produces a document tree from a JSON markup text string that contains a
complete document
-@param root a reference to a pointer to a json_t type. The function
allocates memory to the passed pointer and sets up the value
-@param text a c-string containing a complete JSON text document
-@return a pointer to the new document tree or NULL if some error occurred
-**/
- enum json_error json_parse_document (json_t ** root, char *text);
-
-
-/**
-Function to perform a SAX-like parsing of any JSON document or document
fragment that is passed to it
-@param jsps a structure holding the status information of the current
parser
-@param jsf a structure holding the function pointers to the event functions
-@param c the character to be parsed
-@return a json_error code informing how the parsing went
-**/
- enum json_error json_saxy_parse (struct json_saxy_parser_status *jsps,
struct json_saxy_functions *jsf, char c);
-
-
-/**
-Searches through the object's children for a label holding the text
text_label
-@param object a json_value of type JSON_OBJECT
-@param text_label the c-string to search for through the object's child
labels
-@return a pointer to the first label holding a text equal to text_label or
NULL if there is no such label or if object has no children
-**/
- json_t *json_find_first_label (const json_t * object, const char
*text_label);
-
+ This is a basic JSON emitter.
+ It prints JSON-formatted data to stdout without creating
+ an in-memory tree.
+*/
+
+/* json emitter structure */
+typedef struct __json_emitter {
+ uint32 comma_level;
+ uint32 object_level;
+} json_emitter;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void json_emit_init(json_emitter * je);
+
+void json_emit_object_start(json_emitter * je);
+
+void json_emit_object_end(json_emitter * je);
+
+void json_emit_array_start(json_emitter * je);
+
+void json_emit_array_end(json_emitter * je);
+
+void json_emit_boolean(json_emitter * je, byte value);
+
+void json_emit_null(json_emitter * je);
+
+void json_emit_number(json_emitter * je, number64 value);
+
+void json_emit_string(json_emitter * je, const char * str, size_t bytes);
#ifdef __cplusplus
}
-#endif
-#endif
+#endif /* __cplusplus */
+
+#endif /* __JSON_H__ */
==============================================================================
Revision: 89b2f867f02d
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 07:53:46 2012
Log: Completed the simple JSON emitter.
http://code.google.com/p/flvmeta/source/detail?r=89b2f867f02d
Modified:
/src/dump_json.c
/src/json.c
/src/json.h
=======================================
--- /src/dump_json.c Tue Apr 3 02:23:47 2012
+++ /src/dump_json.c Mon Apr 30 07:53:46 2012
@@ -29,67 +29,68 @@
#include <string.h>
/* JSON metadata dumping */
-static void amf_to_json(const amf_data * data, json_t ** object) {
+static void json_amf_data_dump(const amf_data * data, json_emitter * je) {
if (data != NULL) {
- json_t * value;
amf_node * node;
time_t time;
struct tm * t;
char str[128];
- char * escaped_str;
switch (data->type) {
case AMF_TYPE_NUMBER:
- sprintf(str, "%.12g", data->number_data);
- *object = json_new_number(str);
+ json_emit_number(je, data->number_data);
break;
case AMF_TYPE_BOOLEAN:
- *object = (data->boolean_data) ? json_new_true() :
json_new_false();
+ json_emit_boolean(je, data->boolean_data);
break;
case AMF_TYPE_STRING:
- escaped_str = json_escape((char
*)amf_string_get_bytes(data));
- *object = json_new_string(escaped_str);
- free(escaped_str);
+ json_emit_string(je, (char *)amf_string_get_bytes(data),
amf_string_get_size(data));
break;
case AMF_TYPE_OBJECT:
- *object = json_new_object();
+ json_emit_object_start(je);
node = amf_object_first(data);
while (node != NULL) {
- amf_to_json(amf_object_get_data(node), &value);
- escaped_str = json_escape((char
*)amf_string_get_bytes(amf_object_get_name(node)));
- json_insert_pair_into_object(*object, escaped_str,
value);
- free(escaped_str);
+ json_emit_object_key(je,
+ (char
*)amf_string_get_bytes(amf_object_get_name(node)),
+ amf_string_get_size(amf_object_get_name(node))
+ );
+ json_amf_data_dump(amf_object_get_data(node), je);
node = amf_object_next(node);
}
+ json_emit_object_end(je);
break;
case AMF_TYPE_NULL:
case AMF_TYPE_UNDEFINED:
- *object = json_new_null();
+ json_emit_null(je);
break;
case AMF_TYPE_ASSOCIATIVE_ARRAY:
- *object = json_new_object();
+ json_emit_object_start(je);
node = amf_associative_array_first(data);
while (node != NULL) {
- amf_to_json(amf_associative_array_get_data(node),
&value);
- json_insert_pair_into_object(*object, (const char
*)amf_string_get_bytes(amf_associative_array_get_name(node)), value);
+ json_emit_object_key(je,
+ (char
*)amf_string_get_bytes(amf_associative_array_get_name(node)),
+
amf_string_get_size(amf_associative_array_get_name(node))
+ );
+ json_amf_data_dump(amf_object_get_data(node), je);
node = amf_associative_array_next(node);
}
+ json_emit_object_end(je);
break;
case AMF_TYPE_ARRAY:
- *object = json_new_array();
+ json_emit_array_start(je);
node = amf_array_first(data);
while (node != NULL) {
- amf_to_json(amf_array_get(node), &value);
- json_insert_child(*object, value);
+ json_amf_data_dump(amf_array_get(node), je);
node = amf_array_next(node);
}
+ json_emit_array_end(je);
break;
case AMF_TYPE_DATE:
time = amf_date_to_time_t(data);
tzset();
t = localtime(&time);
strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%S", t);
- *object = json_new_string(str);
+ json_emit_string(je, str, strlen(str));
break;
case AMF_TYPE_XML: break;
case AMF_TYPE_CLASS: break;
@@ -142,16 +143,11 @@
}
static int json_on_metadata_tag(flv_tag * tag, amf_data * name, amf_data *
data, flv_parser * parser) {
- json_t * root;
+ json_emitter je;
+ json_emit_init(&je);
printf("\"scriptDataObject\":{\"name\":\"%s\",\"metadata\":",
amf_string_get_bytes(name));
- root = NULL;
- /* dump AMF into JSON */
- amf_to_json(data, &root);
- /* print data */
- json_stream_output(stdout, root);
- /* cleanup */
- json_free_value(&root);
+ json_amf_data_dump(data, &je);
printf("}");
return OK;
}
@@ -205,15 +201,11 @@
}
int dump_json_amf_data(const amf_data * data) {
- json_t * root;
-
- root = NULL;
+ json_emitter je;
+ json_emit_init(&je);
+
/* dump AMF into JSON */
- amf_to_json(data, &root);
- /* print data */
- json_stream_output(stdout, root);
- /* cleanup */
- json_free_value(&root);
+ json_amf_data_dump(data, &je);
printf("\n");
=======================================
--- /src/json.c Tue Apr 17 13:58:52 2012
+++ /src/json.c Mon Apr 30 07:53:46 2012
@@ -25,39 +25,83 @@
#include <stdio.h>
#include "json.h"
-void json_emit_init(json_emitter * je) {
- je->comma_level = 0;
- je->object_level = 0;
+static void json_print_string(const char * str, size_t bytes) {
+ size_t i;
+ printf("\"");
+ for (i = 0; i < bytes; ++i) {
+ switch (str[i]) {
+ case '\"': printf("\\\""); break;
+ case '\\': printf("\\\\"); break;
+ case '/': printf("\\/"); break;
+ case '\b': printf("\\b"); break;
+ case '\f': printf("\\f"); break;
+ case '\n': printf("\\n"); break;
+ case '\r': printf("\\r"); break;
+ case '\t': printf("\\t"); break;
+ default: printf("%c", str[i]);
+ }
+ }
+ printf("\"");
}
-void json_emit_object_start(json_emitter * je) {
- if (je->comma_level > 0) {
+static void json_print_comma(json_emitter * je) {
+ if (je->print_comma != 0) {
printf(",");
- --je->comma_level;
- }
+ je->print_comma = 0;
+ }
+}
+
+void json_emit_init(json_emitter * je) {
+ je->print_comma = 0;
+}
+
+void json_emit_object_start(json_emitter * je) {
+ json_print_comma(je);
printf("{");
- ++je->object_level;
+}
+
+void json_emit_object_key(json_emitter * je, const char * str, size_t
bytes) {
+ json_print_comma(je);
+ json_print_string(str, bytes);
+ printf(":");
+ je->print_comma = 0;
}
void json_emit_object_end(json_emitter * je) {
printf("}");
- --je->object_level;
+ je->print_comma = 1;
}
void json_emit_array_start(json_emitter * je) {
+ json_print_comma(je);
+ printf("[");
}
void json_emit_array_end(json_emitter * je) {
+ printf("]");
+ je->print_comma = 1;
}
void json_emit_boolean(json_emitter * je, byte value) {
+ json_print_comma(je);
+ printf("%s", value != 0 ? "true" : "false");
+ je->print_comma = 1;
}
void json_emit_null(json_emitter * je) {
+ json_print_comma(je);
+ printf("null");
+ je->print_comma = 1;
}
void json_emit_number(json_emitter * je, number64 value) {
+ json_print_comma(je);
+ printf("%.12g", value);
+ je->print_comma = 1;
}
void json_emit_string(json_emitter * je, const char * str, size_t bytes) {
-}
+ json_print_comma(je);
+ json_print_string(str, bytes);
+ je->print_comma = 1;
+}
=======================================
--- /src/json.h Tue Apr 17 13:58:52 2012
+++ /src/json.h Mon Apr 30 07:53:46 2012
@@ -35,8 +35,7 @@
/* json emitter structure */
typedef struct __json_emitter {
- uint32 comma_level;
- uint32 object_level;
+ byte print_comma;
} json_emitter;
@@ -48,6 +47,8 @@
void json_emit_object_start(json_emitter * je);
+void json_emit_object_key(json_emitter * je, const char * str, size_t
bytes);
+
void json_emit_object_end(json_emitter * je);
void json_emit_array_start(json_emitter * je);
==============================================================================
Revision: d53ec465f52e
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 08:02:12 2012
Log: Merged feature/simple_json.
http://code.google.com/p/flvmeta/source/detail?r=d53ec465f52e
==============================================================================
Revision: f2aa9dae1f6a
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 08:04:28 2012
Log: Removed man page reference to mjson.
http://code.google.com/p/flvmeta/source/detail?r=f2aa9dae1f6a
Modified:
/man/
flvmeta.1.md
=======================================
--- /man/
flvmeta.1.md Sun Apr 29 11:50:39 2012
+++ /man/
flvmeta.1.md Mon Apr 30 08:04:28 2012
@@ -51,8 +51,6 @@
Its memory usage remains minimal, as it uses a two-pass reading algorithm
which
permits the computation of all necessary tags without loading anything
more than
the file's tags headers in memory.
-Only the dumping of JSON data can consume more memory, since the bundled
`mjson`
-library constructs a data tree in memory before outputting the formatted
data.
# COMMANDS
==============================================================================
Revision: f818fc9f6bb5
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 07:57:24 2012
Log: Added missing static function modifiers.
http://code.google.com/p/flvmeta/source/detail?r=f818fc9f6bb5
Modified:
/src/dump_yaml.c
=======================================
--- /src/dump_yaml.c Sun Apr 22 02:58:28 2012
+++ /src/dump_yaml.c Mon Apr 30 07:57:24 2012
@@ -119,7 +119,7 @@
/* YAML FLV file full dump callbacks */
-int yaml_on_header(flv_header * header, flv_parser * parser) {
+static int yaml_on_header(flv_header * header, flv_parser * parser) {
yaml_emitter_t * emitter;
yaml_event_t event;
char buffer[20];
@@ -184,7 +184,7 @@
}
}
-int yaml_on_tag(flv_tag * tag, flv_parser * parser) {
+static int yaml_on_tag(flv_tag * tag, flv_parser * parser) {
const char * str;
yaml_emitter_t * emitter;
yaml_event_t event;
@@ -231,7 +231,7 @@
return OK;
}
-int yaml_on_video_tag(flv_tag * tag, flv_video_tag vt, flv_parser *
parser) {
+static int yaml_on_video_tag(flv_tag * tag, flv_video_tag vt, flv_parser *
parser) {
const char * str;
yaml_emitter_t * emitter;
yaml_event_t event;
@@ -266,7 +266,7 @@
return OK;
}
-int yaml_on_audio_tag(flv_tag * tag, flv_audio_tag at, flv_parser *
parser) {
+static int yaml_on_audio_tag(flv_tag * tag, flv_audio_tag at, flv_parser *
parser) {
const char * str;
yaml_emitter_t * emitter;
yaml_event_t event;
@@ -317,7 +317,7 @@
return OK;
}
-int yaml_on_metadata_tag(flv_tag * tag, amf_data * name, amf_data * data,
flv_parser * parser) {
+static int yaml_on_metadata_tag(flv_tag * tag, amf_data * name, amf_data *
data, flv_parser * parser) {
yaml_emitter_t * emitter;
yaml_event_t event;
@@ -331,7 +331,7 @@
return OK;
}
-int yaml_on_prev_tag_size(uint32 size, flv_parser * parser) {
+static int yaml_on_prev_tag_size(uint32 size, flv_parser * parser) {
yaml_emitter_t * emitter;
yaml_event_t event;
@@ -343,7 +343,7 @@
return OK;
}
-int yaml_on_stream_end(flv_parser * parser) {
+static int yaml_on_stream_end(flv_parser * parser) {
yaml_emitter_t * emitter;
yaml_event_t event;
@@ -368,7 +368,7 @@
}
/* YAML FLV file metadata dump callbacks */
-int yaml_on_metadata_tag_only(flv_tag * tag, amf_data * name, amf_data *
data, flv_parser * parser) {
+static int yaml_on_metadata_tag_only(flv_tag * tag, amf_data * name,
amf_data * data, flv_parser * parser) {
flvmeta_opts * options = (flvmeta_opts*) parser->user_data;
if (options->metadata_event == NULL) {
==============================================================================
Revision: e1d582d9f528
Author: Marc Noirot <
marc....@gmail.com>
Date: Mon Apr 30 08:42:22 2012
Log: Refactored the file dumping process so memory leaks are easier to
avoid.
Fixed a few function definitions.
http://code.google.com/p/flvmeta/source/detail?r=e1d582d9f528
Modified:
/src/dump.c
/src/dump_json.c
/src/dump_json.h
/src/dump_raw.c
/src/dump_raw.h
/src/dump_xml.c
/src/dump_xml.h
/src/dump_yaml.c
/src/dump_yaml.h
=======================================
--- /src/dump.c Tue Apr 3 02:23:47 2012
+++ /src/dump.c Mon Apr 30 08:42:22 2012
@@ -145,20 +145,16 @@
switch (options->dump_format) {
case FLVMETA_FORMAT_JSON:
- dump_json_setup_file_dump(&parser);
- break;
+ return dump_json_file(&parser, options);
case FLVMETA_FORMAT_RAW:
- dump_raw_setup_file_dump(&parser);
- break;
+ return dump_raw_file(&parser, options);
case FLVMETA_FORMAT_XML:
- dump_xml_setup_file_dump(&parser);
- break;
+ return dump_xml_file(&parser, options);
case FLVMETA_FORMAT_YAML:
- dump_yaml_setup_file_dump(&parser);
- break;
- }
-
- return flv_parse(options->input_file, &parser);
+ return dump_yaml_file(&parser, options);
+ default:
+ return OK;
+ }
}
/* dump AMF data directly */
=======================================
--- /src/dump_json.c Mon Apr 30 07:53:46 2012
+++ /src/dump_json.c Mon Apr 30 08:42:22 2012
@@ -188,16 +188,16 @@
}
}
-void dump_json_setup_file_dump(flv_parser * parser) {
- if (parser != NULL) {
- parser->on_header = json_on_header;
- parser->on_tag = json_on_tag;
- parser->on_audio_tag = json_on_audio_tag;
- parser->on_video_tag = json_on_video_tag;
- parser->on_metadata_tag = json_on_metadata_tag;
- parser->on_prev_tag_size = json_on_prev_tag_size;
- parser->on_stream_end = json_on_stream_end;
- }
+int dump_json_file(flv_parser * parser, const flvmeta_opts * options) {
+ parser->on_header = json_on_header;
+ parser->on_tag = json_on_tag;
+ parser->on_audio_tag = json_on_audio_tag;
+ parser->on_video_tag = json_on_video_tag;
+ parser->on_metadata_tag = json_on_metadata_tag;
+ parser->on_prev_tag_size = json_on_prev_tag_size;
+ parser->on_stream_end = json_on_stream_end;
+
+ return flv_parse(options->input_file, parser);
}
int dump_json_amf_data(const amf_data * data) {
=======================================
--- /src/dump_json.h Tue Apr 3 02:23:47 2012
+++ /src/dump_json.h Mon Apr 30 08:42:22 2012
@@ -32,7 +32,7 @@
/* JSON dumping functions */
void dump_json_setup_metadata_dump(flv_parser * parser);
-void dump_json_setup_file_dump(flv_parser * parser);
+int dump_json_file(flv_parser * parser, const flvmeta_opts * options);
int dump_json_amf_data(const amf_data * data);
#ifdef __cplusplus
=======================================
--- /src/dump_raw.c Tue Apr 3 02:23:47 2012
+++ /src/dump_raw.c Mon Apr 30 08:42:22 2012
@@ -122,16 +122,16 @@
}
}
-void dump_raw_setup_file_dump(flv_parser * parser) {
- if (parser != NULL) {
- parser->on_header = raw_on_header;
- parser->on_tag = raw_on_tag;
- parser->on_audio_tag = raw_on_audio_tag;
- parser->on_video_tag = raw_on_video_tag;
- parser->on_metadata_tag = raw_on_metadata_tag;
- parser->on_prev_tag_size = raw_on_prev_tag_size;
- parser->on_stream_end = raw_on_stream_end;
- }
+int dump_raw_file(flv_parser * parser, const flvmeta_opts * options) {
+ parser->on_header = raw_on_header;
+ parser->on_tag = raw_on_tag;
+ parser->on_audio_tag = raw_on_audio_tag;
+ parser->on_video_tag = raw_on_video_tag;
+ parser->on_metadata_tag = raw_on_metadata_tag;
+ parser->on_prev_tag_size = raw_on_prev_tag_size;
+ parser->on_stream_end = raw_on_stream_end;
+
+ return flv_parse(options->input_file, parser);
}
int dump_raw_amf_data(const amf_data * data) {
=======================================
--- /src/dump_raw.h Tue Apr 3 02:23:47 2012
+++ /src/dump_raw.h Mon Apr 30 08:42:22 2012
@@ -32,7 +32,7 @@
/* raw dumping functions */
void dump_raw_setup_metadata_dump(flv_parser * parser);
-void dump_raw_setup_file_dump(flv_parser * parser);
+int dump_raw_file(flv_parser * parser, const flvmeta_opts * options);
int dump_raw_amf_data(const amf_data * data);
#ifdef __cplusplus
=======================================
--- /src/dump_xml.c Tue Apr 3 02:23:47 2012
+++ /src/dump_xml.c Mon Apr 30 08:42:22 2012
@@ -239,16 +239,16 @@
}
}
-void dump_xml_setup_file_dump(flv_parser * parser) {
- if (parser != NULL) {
- parser->on_header = xml_on_header;
- parser->on_tag = xml_on_tag;
- parser->on_audio_tag = xml_on_audio_tag;
- parser->on_video_tag = xml_on_video_tag;
- parser->on_metadata_tag = xml_on_metadata_tag;
- parser->on_prev_tag_size = xml_on_prev_tag_size;
- parser->on_stream_end = xml_on_stream_end;
- }
+int dump_xml_file(flv_parser * parser, const flvmeta_opts * options) {
+ parser->on_header = xml_on_header;
+ parser->on_tag = xml_on_tag;
+ parser->on_audio_tag = xml_on_audio_tag;
+ parser->on_video_tag = xml_on_video_tag;
+ parser->on_metadata_tag = xml_on_metadata_tag;
+ parser->on_prev_tag_size = xml_on_prev_tag_size;
+ parser->on_stream_end = xml_on_stream_end;
+
+ return flv_parse(options->input_file, parser);
}
int dump_xml_amf_data(const amf_data * data) {
=======================================
--- /src/dump_xml.h Tue Apr 3 02:23:47 2012
+++ /src/dump_xml.h Mon Apr 30 08:42:22 2012
@@ -31,9 +31,9 @@
#endif /* __cplusplus */
/* XML dumping functions */
-extern void dump_xml_setup_metadata_dump(flv_parser * parser);
-extern void dump_xml_setup_file_dump(flv_parser * parser);
-extern int dump_xml_amf_data(const amf_data * data);
+void dump_xml_setup_metadata_dump(flv_parser * parser);
+int dump_xml_file(flv_parser * parser, const flvmeta_opts * options);
+int dump_xml_amf_data(const amf_data * data);
#ifdef __cplusplus
}
=======================================
--- /src/dump_yaml.c Mon Apr 30 07:57:24 2012
+++ /src/dump_yaml.c Mon Apr 30 08:42:22 2012
@@ -124,64 +124,51 @@
yaml_event_t event;
char buffer[20];
- emitter = (yaml_emitter_t *)malloc(sizeof(yaml_emitter_t));
- if (emitter != NULL) {
- yaml_emitter_initialize(emitter);
- parser->user_data = emitter;
-
- yaml_emitter_set_output_file(emitter, stdout);
- yaml_emitter_open(emitter);
-
- yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
- yaml_emitter_emit(emitter, &event);
-
- yaml_mapping_start_event_initialize(&event, NULL, NULL, 1,
YAML_ANY_MAPPING_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- /* magic */
- yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)"magic", 5, 1, 1, YAML_ANY_SCALAR_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- sprintf(buffer, "%.3s", header->signature);
- yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- /* hasVideo */
- yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)"hasVideo", 8, 1, 1, YAML_ANY_SCALAR_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- sprintf(buffer, "%s",
flv_header_has_video(*header) ? "true" : "false");
- yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- /* hasAudio */
- yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)"hasAudio", 8, 1, 1, YAML_ANY_SCALAR_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- sprintf(buffer, "%s",
flv_header_has_audio(*header) ? "true" : "false");
- yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- /* version */
- yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)"version", 7, 1, 1, YAML_ANY_SCALAR_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- sprintf(buffer, "%i", header->version);
- yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)buffer, (int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- /* start of tags array */
- yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)"tags", 4, 1, 1, YAML_ANY_SCALAR_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- yaml_sequence_start_event_initialize(&event, NULL, NULL, 1,
YAML_ANY_SEQUENCE_STYLE);
- yaml_emitter_emit(emitter, &event);
-
- return OK;
- }
- else {
- return ERROR_MEMORY;
- }
+ emitter = (yaml_emitter_t *)parser->user_data;
+
+ yaml_mapping_start_event_initialize(&event, NULL, NULL, 1,
YAML_ANY_MAPPING_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ /* magic */
+ yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)"magic", 5, 1, 1, YAML_ANY_SCALAR_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ sprintf(buffer, "%.3s", header->signature);
+ yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer,
(int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ /* hasVideo */
+ yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)"hasVideo", 8, 1, 1, YAML_ANY_SCALAR_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ sprintf(buffer, "%s",
flv_header_has_video(*header) ? "true" : "false");
+ yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer,
(int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ /* hasAudio */
+ yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)"hasAudio", 8, 1, 1, YAML_ANY_SCALAR_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ sprintf(buffer, "%s",
flv_header_has_audio(*header) ? "true" : "false");
+ yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer,
(int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ /* version */
+ yaml_scalar_event_initialize(&event, NULL, NULL,
(yaml_char_t*)"version", 7, 1, 1, YAML_ANY_SCALAR_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ sprintf(buffer, "%i", header->version);
+ yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)buffer,
(int)strlen(buffer), 1, 1, YAML_ANY_SCALAR_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ /* start of tags array */
+ yaml_scalar_event_initialize(&event, NULL, NULL, (yaml_char_t*)"tags",
4, 1, 1, YAML_ANY_SCALAR_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ yaml_sequence_start_event_initialize(&event, NULL, NULL, 1,
YAML_ANY_SEQUENCE_STYLE);
+ yaml_emitter_emit(emitter, &event);
+
+ return OK;
}
static int yaml_on_tag(flv_tag * tag, flv_parser * parser) {
@@ -355,15 +342,6 @@
yaml_mapping_end_event_initialize(&event);
yaml_emitter_emit(emitter, &event);
- yaml_document_end_event_initialize(&event, 1);
- yaml_emitter_emit(emitter, &event);
-
- yaml_emitter_flush(emitter);
- yaml_emitter_close(emitter);
- yaml_emitter_delete(emitter);
-
- free(emitter);
-
return OK;
}
@@ -392,16 +370,38 @@
}
}
-void dump_yaml_setup_file_dump(flv_parser * parser) {
- if (parser != NULL) {
- parser->on_header = yaml_on_header;
- parser->on_tag = yaml_on_tag;
- parser->on_audio_tag = yaml_on_audio_tag;
- parser->on_video_tag = yaml_on_video_tag;
- parser->on_metadata_tag = yaml_on_metadata_tag;
- parser->on_prev_tag_size = yaml_on_prev_tag_size;
- parser->on_stream_end = yaml_on_stream_end;
- }
+int dump_yaml_file(flv_parser * parser, const flvmeta_opts * options) {
+ yaml_emitter_t emitter;
+ yaml_event_t event;
+ int ret;
+
+ parser->on_header = yaml_on_header;
+ parser->on_tag = yaml_on_tag;
+ parser->on_audio_tag = yaml_on_audio_tag;
+ parser->on_video_tag = yaml_on_video_tag;
+ parser->on_metadata_tag = yaml_on_metadata_tag;
+ parser->on_prev_tag_size = yaml_on_prev_tag_size;
+ parser->on_stream_end = yaml_on_stream_end;
+
+ yaml_emitter_initialize(&emitter);
+ yaml_emitter_set_output_file(&emitter, stdout);
+ yaml_emitter_open(&emitter);
+
+ yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
+ yaml_emitter_emit(&emitter, &event);
+
+ parser->user_data = &emitter;
+
+ ret = flv_parse(options->input_file, parser);
+
+ yaml_document_end_event_initialize(&event, 1);
+ yaml_emitter_emit(&emitter, &event);
+
+ yaml_emitter_flush(&emitter);
+ yaml_emitter_close(&emitter);
+ yaml_emitter_delete(&emitter);
+
+ return ret;
}
int dump_yaml_amf_data(const amf_data * data) {
=======================================
--- /src/dump_yaml.h Tue Apr 3 02:23:47 2012
+++ /src/dump_yaml.h Mon Apr 30 08:42:22 2012
@@ -31,9 +31,9 @@
#endif /* __cplusplus */
/* YAML dumping functions */
-extern void dump_yaml_setup_metadata_dump(flv_parser * parser);
-extern void dump_yaml_setup_file_dump(flv_parser * parser);
-extern int dump_yaml_amf_data(const amf_data * data);
+void dump_yaml_setup_metadata_dump(flv_parser * parser);
+int dump_yaml_file(flv_parser * parser, const flvmeta_opts * options);
+int dump_yaml_amf_data(const amf_data * data);
#ifdef __cplusplus
}
==============================================================================
Revision: 8434bd423217
Author: Marc Noirot <
marc....@gmail.com>
Date: Tue May 1 13:10:40 2012
Log: Fixed JSON dumping to prevent potential invalid output.
http://code.google.com/p/flvmeta/source/detail?r=8434bd423217
Modified:
/src/dump_json.c
/src/json.c
/src/json.h
=======================================
--- /src/dump_json.c Mon Apr 30 08:42:22 2012
+++ /src/dump_json.c Tue May 1 13:10:40 2012
@@ -102,63 +102,106 @@
/* JSON FLV file full dump callbacks */
static int json_on_header(flv_header * header, flv_parser * parser) {
-
printf("{\"magic\":\"%.3s\",\"hasVideo\":%s,\"hasAudio\":%s,\"version\":%i,\"tags\":[",
- header->signature,
- flv_header_has_video(*header) ? "true" : "false",
- flv_header_has_audio(*header) ? "true" : "false",
- header->version);
+ json_emitter * je;
+ je = (json_emitter*)parser->user_data;
+
+ json_emit_object_start(je);
+ json_emit_object_key_z(je, "magic");
+ json_emit_string(je, (char*)header->signature, 3);
+ json_emit_object_key_z(je, "hasVideo");
+ json_emit_boolean(je, flv_header_has_video(*header));
+ json_emit_object_key_z(je, "hasAudio");
+ json_emit_boolean(je, flv_header_has_audio(*header));
+ json_emit_object_key_z(je, "version");
+ json_emit_integer(je, header->version);
+ json_emit_object_key_z(je, "tags");
+ json_emit_array_start(je);
+
return OK;
}
static int json_on_tag(flv_tag * tag, flv_parser * parser) {
- if (parser->user_data != NULL) {
- printf(",");
- }
- else {
- parser->user_data = tag;
- }
-
- printf("{\"type\":\"%s\",\"timestamp\":%i,\"dataSize\":%i",
- dump_string_get_tag_type(tag),
- flv_tag_get_timestamp(*tag),
- flv_tag_get_body_length(*tag));
- printf(",\"offset\":%" FILE_OFFSET_PRINTF_FORMAT "i,",
- parser->stream->current_tag_offset);
+ json_emitter * je;
+ je = (json_emitter*)parser->user_data;
+
+ json_emit_object_start(je);
+ json_emit_object_key_z(je, "type");
+ json_emit_string_z(je, dump_string_get_tag_type(tag));
+ json_emit_object_key_z(je, "timestamp");
+ json_emit_integer(je, flv_tag_get_timestamp(*tag));
+ json_emit_object_key_z(je, "dataSize");
+ json_emit_integer(je, flv_tag_get_body_length(*tag));
+ json_emit_object_key_z(je, "offset");
+ json_emit_file_offset(je, parser->stream->current_tag_offset);
return OK;
}
static int json_on_video_tag(flv_tag * tag, flv_video_tag vt, flv_parser *
parser) {
- printf("\"videoData\":{\"codecID\":\"%s\"",
dump_string_get_video_codec(vt));
- printf(",\"frameType\":\"%s\"}", dump_string_get_video_frame_type(vt));
+ json_emitter * je;
+ je = (json_emitter*)parser->user_data;
+
+ json_emit_object_key_z(je, "videoData");
+ json_emit_object_start(je);
+ json_emit_object_key_z(je, "codecID");
+ json_emit_string_z(je, dump_string_get_video_codec(vt));
+ json_emit_object_key_z(je, "frameType");
+ json_emit_string_z(je, dump_string_get_video_frame_type(vt));
+ json_emit_object_end(je);
+
return OK;
}
static int json_on_audio_tag(flv_tag * tag, flv_audio_tag at, flv_parser *
parser) {
- printf("\"audioData\":{\"type\":\"%s\"",
dump_string_get_sound_type(at));
- printf(",\"size\":\"%s\"", dump_string_get_sound_size(at));
- printf(",\"rate\":\"%s\"", dump_string_get_sound_rate(at));
- printf(",\"format\":\"%s\"}", dump_string_get_sound_format(at));
+ json_emitter * je;
+ je = (json_emitter*)parser->user_data;
+
+ json_emit_object_key_z(je, "audioData");
+ json_emit_object_start(je);
+ json_emit_object_key_z(je, "type");
+ json_emit_string_z(je, dump_string_get_sound_type(at));
+ json_emit_object_key_z(je, "size");
+ json_emit_string_z(je, dump_string_get_sound_size(at));
+ json_emit_object_key_z(je, "rate");
+ json_emit_string_z(je, dump_string_get_sound_rate(at));
+ json_emit_object_key_z(je, "format");
+ json_emit_string_z(je, dump_string_get_sound_format(at));
+ json_emit_object_end(je);
+
return OK;
}
static int json_on_metadata_tag(flv_tag * tag, amf_data * name, amf_data *
data, flv_parser * parser) {
- json_emitter je;
- json_emit_init(&je);
-
- printf("\"scriptDataObject\":{\"name\":\"%s\",\"metadata\":",
amf_string_get_bytes(name));
- json_amf_data_dump(data, &je);
- printf("}");
+ json_emitter * je;
+ je = (json_emitter*)parser->user_data;
+
+ json_emit_object_key_z(je, "scriptDataObject");
+ json_emit_object_start(je);
+ json_emit_object_key_z(je, "name");
+ json_emit_string(je, (char*)amf_string_get_bytes(name),
amf_string_get_size(name));
+ json_emit_object_key_z(je, "metadata");
+ json_amf_data_dump(data, je);
+ json_emit_object_end(je);
+
return OK;
}
static int json_on_prev_tag_size(uint32 size, flv_parser * parser) {
- printf("}");
+ json_emitter * je;
+ je = (json_emitter*)parser->user_data;
+
+ json_emit_object_end(je);
+
return OK;
}
static int json_on_stream_end(flv_parser * parser) {
- printf("]}");
+ json_emitter * je;
+ je = (json_emitter*)parser->user_data;
+
+ json_emit_array_end(je);
+ json_emit_object_end(je);
+
return OK;
}
@@ -189,6 +232,8 @@
}
int dump_json_file(flv_parser * parser, const flvmeta_opts * options) {
+ json_emitter je;
+
parser->on_header = json_on_header;
parser->on_tag = json_on_tag;
parser->on_audio_tag = json_on_audio_tag;
@@ -197,6 +242,9 @@
parser->on_prev_tag_size = json_on_prev_tag_size;
parser->on_stream_end = json_on_stream_end;
+ json_emit_init(&je);
+ parser->user_data = &je;
+
return flv_parse(options->input_file, parser);
}
=======================================
--- /src/json.c Mon Apr 30 07:53:46 2012
+++ /src/json.c Tue May 1 13:10:40 2012
@@ -23,6 +23,7 @@
*/
#include <stdio.h>
+#include <string.h>
#include "json.h"
static void json_print_string(const char * str, size_t bytes) {
@@ -66,6 +67,13 @@
printf(":");
je->print_comma = 0;
}
+
+void json_emit_object_key_z(json_emitter * je, const char * str) {
+ json_print_comma(je);
+ json_print_string(str, strlen(str));
+ printf(":");
+ je->print_comma = 0;
+}
void json_emit_object_end(json_emitter * je) {
printf("}");
@@ -93,6 +101,18 @@
printf("null");
je->print_comma = 1;
}
+
+void json_emit_integer(json_emitter * je, int value) {
+ json_print_comma(je);
+ printf("%i", value);
+ je->print_comma = 1;
+}
+
+void json_emit_file_offset(json_emitter * je, file_offset_t value) {
+ json_print_comma(je);
+ printf("%" FILE_OFFSET_PRINTF_FORMAT "i", value);
+ je->print_comma = 1;
+}
void json_emit_number(json_emitter * je, number64 value) {
json_print_comma(je);
@@ -105,3 +125,9 @@
json_print_string(str, bytes);
je->print_comma = 1;
}
+
+void json_emit_string_z(json_emitter * je, const char * str) {
+ json_print_comma(je);
+ json_print_string(str, strlen(str));
+ je->print_comma = 1;
+}
=======================================
--- /src/json.h Mon Apr 30 07:53:46 2012
+++ /src/json.h Tue May 1 13:10:40 2012
@@ -49,6 +49,8 @@
void json_emit_object_key(json_emitter * je, const char * str, size_t
bytes);
+void json_emit_object_key_z(json_emitter * je, const char * str);
+
void json_emit_object_end(json_emitter * je);
void json_emit_array_start(json_emitter * je);
@@ -59,10 +61,16 @@
void json_emit_null(json_emitter * je);
+void json_emit_integer(json_emitter * je, int value);
+
+void json_emit_file_offset(json_emitter * je, file_offset_t value);
+
void json_emit_number(json_emitter * je, number64 value);
void json_emit_string(json_emitter * je, const char * str, size_t bytes);
+void json_emit_string_z(json_emitter * je, const char * str);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
==============================================================================
Revision: bfa013b67fd5
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 03:45:24 2012
Log: Improved current git commit detection.
http://code.google.com/p/flvmeta/source/detail?r=bfa013b67fd5
Modified:
/CMakeLists.txt
=======================================
--- /CMakeLists.txt Mon Apr 30 02:40:24 2012
+++ /CMakeLists.txt Thu May 3 03:45:24 2012
@@ -1,18 +1,21 @@
cmake_minimum_required(VERSION 2.6)
project(flvmeta C)
-set(FLVMETA_VERSION "1.1")
-set(FLVMETA_STABLE no)
-
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR} ${CMAKE_MODULE_PATH})
-# check whether we're in an instable branch
-if(FLVMETA_STABLE)
- message(STATUS "Set flvmeta version to ${FLVMETA_VERSION}")
-else(FLVMETA_STABLE)
- # if so, check for svnversion, and retrieve current revision
+set(FLVMETA_VERSION "1.1")
+set(FLVMETA_RELEASE no)
+
+# check whether we are building a release or a git snapshot
+if(NOT FLVMETA_RELEASE)
+ # check for git
find_program(GIT "git")
- if(GIT)
+ mark_as_advanced(GIT)
+ # check whether we are in a git repository
+ find_file(DOT_GIT ".git" ${CMAKE_SOURCE_DIR})
+ mark_as_advanced(DOT_GIT)
+ if(GIT AND DOT_GIT)
+ # retrieve current revision
execute_process(
COMMAND "${GIT}" rev-parse --short HEAD
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
@@ -20,13 +23,8 @@
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(FLVMETA_VERSION "${FLVMETA_VERSION}-g${GIT_RELEASE}")
- message(STATUS "Set unstable flvmeta version to ${FLVMETA_VERSION}")
- unset(GIT CACHE)
- else(GIT)
- message(STATUS "Git not found, set flvmeta version to
${FLVMETA_VERSION}")
- unset(GIT-NOT_FOUND CACHE)
- endif(GIT)
-endif(FLVMETA_STABLE)
+ endif(GIT AND DOT_GIT)
+endif(NOT FLVMETA_RELEASE)
# generic variables
set(PACKAGE "flvmeta")
==============================================================================
Revision: 986d26cfaff9
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 03:49:12 2012
Log: Moved cmake module to dedicated directory.
http://code.google.com/p/flvmeta/source/detail?r=986d26cfaff9
Added:
/cmake/modules/FindLibYaml.cmake
Deleted:
/FindLibYaml.cmake
Modified:
/NEWS
/
configure.ac
=======================================
--- /dev/null
+++ /cmake/modules/FindLibYaml.cmake Thu May 3 03:49:12 2012
@@ -0,0 +1,13 @@
+# CMake module to search for the libyaml library
+# (library for parsing YAML files)
+# If it's found it sets LIBYAML_FOUND to TRUE
+# and following variables are set:
+# LIBYAML_INCLUDE_DIR
+# LIBYAML_LIBRARY
+
+FIND_PATH(LIBYAML_INCLUDE_DIR NAMES yaml.h)
+FIND_LIBRARY(LIBYAML_LIBRARIES NAMES yaml libyaml)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Yaml DEFAULT_MSG LIBYAML_LIBRARIES
LIBYAML_INCLUDE_DIR)
+MARK_AS_ADVANCED(LIBYAML_INCLUDE_DIR LIBYAML_LIBRARIES)
=======================================
--- /FindLibYaml.cmake Sun Apr 29 09:37:44 2012
+++ /dev/null
@@ -1,13 +0,0 @@
-# CMake module to search for the libyaml library
-# (library for parsing YAML files)
-# If it's found it sets LIBYAML_FOUND to TRUE
-# and following variables are set:
-# LIBYAML_INCLUDE_DIR
-# LIBYAML_LIBRARY
-
-FIND_PATH(LIBYAML_INCLUDE_DIR NAMES yaml.h)
-FIND_LIBRARY(LIBYAML_LIBRARIES NAMES yaml libyaml)
-
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(Yaml DEFAULT_MSG LIBYAML_LIBRARIES
LIBYAML_INCLUDE_DIR)
-MARK_AS_ADVANCED(LIBYAML_INCLUDE_DIR LIBYAML_LIBRARIES)
=======================================
--- /NEWS Sun Apr 29 12:40:32 2012
+++ /NEWS Thu May 3 03:49:12 2012
@@ -1,4 +1,6 @@
-Version 1.2.0 (2012-04-30)
+Version 1.1.0 (2012-05-03)
+ - Beta release. All features should be considered relatively
+ stable unless explicitely stated otherwise.
- Added proper command line handling and help.
- Added the possibility to overwrite the input file
when the output file is not specified or when both files
=======================================
--- /
configure.ac Mon Apr 23 06:57:23 2012
+++ /
configure.ac Thu May 3 03:49:12 2012
@@ -3,7 +3,7 @@
AC_PREREQ(2.61)
-AC_INIT([flvmeta], [1.1], [
flvmeta-d...@googlegroups.com])
+AC_INIT([flvmeta], [1.1.0], [
flvmeta-d...@googlegroups.com])
AC_CONFIG_SRCDIR([
config.h.in])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE
==============================================================================
Revision: e0fa50c387da
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 03:53:24 2012
Log: Updated module search path.
http://code.google.com/p/flvmeta/source/detail?r=e0fa50c387da
Modified:
/CMakeLists.txt
=======================================
--- /CMakeLists.txt Thu May 3 03:45:24 2012
+++ /CMakeLists.txt Thu May 3 03:53:24 2012
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 2.6)
project(flvmeta C)
-set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR} ${CMAKE_MODULE_PATH})
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules
${CMAKE_MODULE_PATH})
set(FLVMETA_VERSION "1.1")
set(FLVMETA_RELEASE no)
@@ -36,7 +36,7 @@
# build options
set(
FLVMETA_USE_SYSTEM_LIBYAML FALSE
- CACHE BOOL "Build flvmeta by linking it to the currently installed
version of libyaml"
+ CACHE BOOL "Link flvmeta to the installed version of libyaml"
)
#platform tests
==============================================================================
Revision: 7e0e09067efc
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 03:54:03 2012
Log: Set version to 1.1.0.
http://code.google.com/p/flvmeta/source/detail?r=7e0e09067efc
Modified:
/CMakeLists.txt
=======================================
--- /CMakeLists.txt Thu May 3 03:53:24 2012
+++ /CMakeLists.txt Thu May 3 03:54:03 2012
@@ -3,8 +3,8 @@
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules
${CMAKE_MODULE_PATH})
-set(FLVMETA_VERSION "1.1")
-set(FLVMETA_RELEASE no)
+set(FLVMETA_VERSION "1.1.0")
+set(FLVMETA_RELEASE yes)
# check whether we are building a release or a git snapshot
if(NOT FLVMETA_RELEASE)
==============================================================================
Revision: c7d3a475cb83
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 05:51:22 2012
Log: Fixed Makefile.am to point to the correct path to
FindLibYaml.cmake.
http://code.google.com/p/flvmeta/source/detail?r=c7d3a475cb83
Modified:
/Makefile.am
=======================================
--- /Makefile.am Sun Apr 29 12:39:28 2012
+++ /Makefile.am Thu May 3 05:51:22 2012
@@ -7,4 +7,4 @@
CMakeLists.txt \
.gitignore \
config-cmake.h.in \
- FindLibYaml.cmake
+ cmake/modules/FindLibYaml.cmake
==============================================================================
Revision: 27ca03eb73f5
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 07:55:51 2012
Log: Added a github README.md file.
http://code.google.com/p/flvmeta/source/detail?r=27ca03eb73f5
Added:
/README.md
=======================================
--- /dev/null
+++ /README.md Thu May 3 07:55:51 2012
@@ -0,0 +1,51 @@
+# FLVmeta - FLV Metadata Editor
+
+flvmeta is a command-line utility aimed at manipulating Adobe(tm) Flash
+Video files (FLV), through several commands, only one of which can be used
for
+each invocation of the program.
+
+It possesses the ability to compute and inject a variety of values in the
+_onMetaData_ event tag, including keyframe indices used by most video
players to
+allow random-access seeking, notably for HTTP pseudo-streamed files via a
+server-side module, by having the client send the file offset looked up
for the
+nearest desired keyframe.
+Tools such as flvmeta must be used in the case the initial encoding process
+is unable to inject those metadata.
+
+It can also optionnally inject the _onLastSecond_ event, used to signal
the end
+of playback, for example to revert the player software to a 'stopped'
state.
+
+flvmeta also has the ability to dump metadata and full file information to
+standard output, in a variety of textual output formats, including XML,
YAML,
+and JSON.
+
+Finally, the program can analyze FLV files to detect potential problems and
+errors, and generate a textual report in a raw format, or in XML.
+It has the ability to detect more than a hundred problems, going from
harmless
+to potentially unplayable, using a few real world encountered issues.
+
+flvmeta can operate on arbitrarily large files, and can handle FLV files
+using extended (32-bit) timestamps.
+It can guess video frame dimensions for all known video codecs supported
by the
+official FLV specification.
+
+Its memory usage remains minimal, as it uses a two-pass reading algorithm
which
+permits the computation of all necessary tags without loading anything
more than
+the file's tags headers in memory.
+
+The FLVmeta source package includes and uses the following software:
+
+* the libyaml YAML parser and emitter
([
http://pyyaml.org/wiki/LibYAML](http://pyyaml.org/wiki/LibYAML "LibYAML")).
+
+
+FLVmeta is provided "as is" with no warranty. The exact terms
+under which you may use and (re)distribute this program are detailed
+in the GNU General Public License, in the file COPYING.
+
+See the files AUTHORS and THANKS for a list of authors and other
contributors.
+
+See the file INSTALL for compilation and installation instructions.
+
+See the file NEWS for a description of major changes in this release.
+
+See the file TODO for ideas on how you could help us improve FLVmeta.
==============================================================================
Revision: 6cd0e7aa7f9b
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 07:56:29 2012
Log: Updated documentation.
http://code.google.com/p/flvmeta/source/detail?r=6cd0e7aa7f9b
Modified:
/README
/man/
flvmeta.1.md
=======================================
--- /README Tue Apr 17 13:57:38 2012
+++ /README Thu May 3 07:56:29 2012
@@ -11,7 +11,7 @@
timestamps.
Since version 1.0.8, it has been able to handle arbitrarily large files.
-The main goal of this program is to write an alternative to tools like
flvtool2.
+This project was started as an alternative to tools like flvtool2.
It is written in portable C, and should compile on most platforms (it has
been successfully compiled and tested on Ubuntu Feisty and later, Debian
Lenny,
MacOSX 10.4, Windows XP, and Windows 7).
=======================================
--- /man/
flvmeta.1.md Mon Apr 30 08:04:28 2012
+++ /man/
flvmeta.1.md Thu May 3 07:56:29 2012
@@ -40,8 +40,6 @@
errors, and generate a textual report in a raw format, or in XML.
It has the ability to detect more than a hundred problems, going from
harmless
to potentially unplayable, using a few real world encountered issues.
-This analysis can also determine and display the minimal Flash Player
version
-which can be used to correctly play a given file, as well as codec
information.
**flvmeta** can operate on arbitrarily large files, and can handle FLV
files
using extended (32-bit) timestamps.
==============================================================================
Revision: cf2a65bd80a1
Author: Marc Noirot <
marc....@gmail.com>
Date: Thu May 3 08:05:20 2012
Log: Renamed FindLibYAML.cmake to better reflect project name.
http://code.google.com/p/flvmeta/source/detail?r=cf2a65bd80a1
Added:
/cmake/modules/FindLibYAML.cmake
Deleted:
/cmake/modules/FindLibYaml.cmake
Modified:
/Makefile.am
/src/CMakeLists.txt
=======================================
--- /dev/null
+++ /cmake/modules/FindLibYAML.cmake Thu May 3 08:05:20 2012
@@ -0,0 +1,13 @@
+# CMake module to search for the libyaml library
+# (library for parsing YAML files)
+# If it's found it sets LIBYAML_FOUND to TRUE
+# and following variables are set:
+# LIBYAML_INCLUDE_DIR
+# LIBYAML_LIBRARY
+
+FIND_PATH(LIBYAML_INCLUDE_DIR NAMES yaml.h)
+FIND_LIBRARY(LIBYAML_LIBRARIES NAMES yaml libyaml)
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Yaml DEFAULT_MSG LIBYAML_LIBRARIES
LIBYAML_INCLUDE_DIR)
+MARK_AS_ADVANCED(LIBYAML_INCLUDE_DIR LIBYAML_LIBRARIES)
=======================================
--- /cmake/modules/FindLibYaml.cmake Thu May 3 03:49:12 2012
+++ /dev/null
@@ -1,13 +0,0 @@
-# CMake module to search for the libyaml library
-# (library for parsing YAML files)
-# If it's found it sets LIBYAML_FOUND to TRUE
-# and following variables are set:
-# LIBYAML_INCLUDE_DIR
-# LIBYAML_LIBRARY
-
-FIND_PATH(LIBYAML_INCLUDE_DIR NAMES yaml.h)
-FIND_LIBRARY(LIBYAML_LIBRARIES NAMES yaml libyaml)
-
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(Yaml DEFAULT_MSG LIBYAML_LIBRARIES
LIBYAML_INCLUDE_DIR)
-MARK_AS_ADVANCED(LIBYAML_INCLUDE_DIR LIBYAML_LIBRARIES)
=======================================
--- /Makefile.am Thu May 3 05:51:22 2012
+++ /Makefile.am Thu May 3 08:05:20 2012
@@ -7,4 +7,4 @@
CMakeLists.txt \
.gitignore \
config-cmake.h.in \
- cmake/modules/FindLibYaml.cmake
+ cmake/modules/FindLibYAML.cmake
=======================================
--- /src/CMakeLists.txt Sun Apr 29 11:48:40 2012
+++ /src/CMakeLists.txt Thu May 3 08:05:20 2012
@@ -56,7 +56,7 @@
# libyaml
if(FLVMETA_USE_SYSTEM_LIBYAML)
# search for libyaml on the system, link with it
- find_package(libyaml REQUIRED)
+ find_package(LibYAML REQUIRED)
include_directories(${LIBYAML_INCLUDE_DIR})
target_link_libraries(flvmeta ${LIBYAML_LIBRARIES})
else(FLVMETA_USE_SYSTEM_LIBYAML)