1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef MEDIA_WEBM_WEBM_PARSER_H_
6#define MEDIA_WEBM_WEBM_PARSER_H_
7
8#include <string>
9#include <vector>
10
11#include "base/basictypes.h"
12#include "media/base/media_export.h"
13
14namespace media {
15
16// Interface for receiving WebM parser events.
17//
18// Each method is called when an element of the specified type is parsed.
19// The ID of the element that was parsed is given along with the value
20// stored in the element. List elements generate calls at the start and
21// end of the list. Any pointers passed to these methods are only guaranteed
22// to be valid for the life of that call. Each method (except for OnListStart)
23// returns a bool that indicates whether the parsed data is valid. OnListStart
24// returns a pointer to a WebMParserClient object, which should be used to
25// handle elements parsed out of the list being started. If false (or NULL by
26// OnListStart) is returned then the parse is immediately terminated and an
27// error is reported by the parser.
28class MEDIA_EXPORT WebMParserClient {
29 public:
30  virtual ~WebMParserClient();
31
32  virtual WebMParserClient* OnListStart(int id);
33  virtual bool OnListEnd(int id);
34  virtual bool OnUInt(int id, int64 val);
35  virtual bool OnFloat(int id, double val);
36  virtual bool OnBinary(int id, const uint8* data, int size);
37  virtual bool OnString(int id, const std::string& str);
38
39 protected:
40  WebMParserClient();
41
42  DISALLOW_COPY_AND_ASSIGN(WebMParserClient);
43};
44
45struct ListElementInfo;
46
47// Parses a WebM list element and all of its children. This
48// class supports incremental parsing of the list so Parse()
49// can be called multiple times with pieces of the list.
50// IsParsingComplete() will return true once the entire list has
51// been parsed.
52class MEDIA_EXPORT WebMListParser {
53 public:
54  // |id| - Element ID of the list we intend to parse.
55  // |client| - Called as different elements in the list are parsed.
56  WebMListParser(int id, WebMParserClient* client);
57  ~WebMListParser();
58
59  // Resets the state of the parser so it can start parsing a new list.
60  void Reset();
61
62  // Parses list data contained in |buf|.
63  //
64  // Returns < 0 if the parse fails.
65  // Returns 0 if more data is needed.
66  // Returning > 0 indicates success & the number of bytes parsed.
67  int Parse(const uint8* buf, int size);
68
69  // Returns true if the entire list has been parsed.
70  bool IsParsingComplete() const;
71
72 private:
73  enum State {
74    NEED_LIST_HEADER,
75    INSIDE_LIST,
76    DONE_PARSING_LIST,
77    PARSE_ERROR,
78  };
79
80  struct ListState {
81    int id_;
82    int64 size_;
83    int64 bytes_parsed_;
84    const ListElementInfo* element_info_;
85    WebMParserClient* client_;
86  };
87
88  void ChangeState(State new_state);
89
90  // Parses a single element in the current list.
91  //
92  // |header_size| - The size of the element header
93  // |id| - The ID of the element being parsed.
94  // |element_size| - The size of the element body.
95  // |data| - Pointer to the element contents.
96  // |size| - Number of bytes in |data|
97  // |client| - Client to pass the parsed data to.
98  //
99  // Returns < 0 if the parse fails.
100  // Returns 0 if more data is needed.
101  // Returning > 0 indicates success & the number of bytes parsed.
102  int ParseListElement(int header_size,
103                       int id, int64 element_size,
104                       const uint8* data, int size);
105
106  // Called when starting to parse a new list.
107  //
108  // |id| - The ID of the new list.
109  // |size| - The size of the new list.
110  // |client| - The client object to notify that a new list is being parsed.
111  //
112  // Returns true if this list can be started in the current context. False
113  // if starting this list causes some sort of parse error.
114  bool OnListStart(int id, int64 size);
115
116  // Called when the end of the current list has been reached. This may also
117  // signal the end of the current list's ancestors if the current list happens
118  // to be at the end of its parent.
119  //
120  // Returns true if no errors occurred while ending this list(s).
121  bool OnListEnd();
122
123  // Checks to see if |id_b| is a sibling or ancestor of |id_a|.
124  bool IsSiblingOrAncestor(int id_a, int id_b) const;
125
126  State state_;
127
128  // Element ID passed to the constructor.
129  const int root_id_;
130
131  // Element level for |root_id_|. Used to verify that elements appear at
132  // the correct level.
133  const int root_level_;
134
135  // WebMParserClient to handle the root list.
136  WebMParserClient* const root_client_;
137
138  // Stack of state for all the lists currently being parsed. Lists are
139  // added and removed from this stack as they are parsed.
140  std::vector<ListState> list_state_stack_;
141
142  DISALLOW_COPY_AND_ASSIGN(WebMListParser);
143};
144
145// Parses an element header & returns the ID and element size.
146//
147// Returns < 0 if the parse fails.
148// Returns 0 if more data is needed.
149// Returning > 0 indicates success & the number of bytes parsed.
150// |*id| contains the element ID on success and is undefined otherwise.
151// |*element_size| contains the element size on success and is undefined
152//                 otherwise.
153int MEDIA_EXPORT WebMParseElementHeader(const uint8* buf, int size,
154                                        int* id, int64* element_size);
155
156}  // namespace media
157
158#endif  // MEDIA_WEBM_WEBM_PARSER_H_
159