Merge pull request #491 from Daniil-Osokin:cvtRGB2YUV420p
[profile/ivi/opencv.git] / doc / ocv.py
1 #/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 """
4     ocv domain, a modified copy of sphinx.domains.cpp + shpinx.domains.python.
5                             The original copyright is below
6     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7
8     The OpenCV C/C++/Python/Java/... language domain.
9
10     :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
11     :license: BSD, see LICENSE for details.
12 """
13
14 import re
15 from copy import deepcopy
16
17 from docutils import nodes
18 from docutils.parsers.rst import directives
19
20 from sphinx import addnodes
21 from sphinx.roles import XRefRole
22 from sphinx.locale import l_, _
23 from sphinx.domains import Domain, ObjType
24 from sphinx.directives import ObjectDescription
25 from sphinx.util.nodes import make_refnode
26 from sphinx.util.compat import Directive
27 from sphinx.util.docfields import Field, GroupedField, TypedField
28
29 ########################### Python Part ###########################
30
31 # REs for Python signatures
32 py_sig_re = re.compile(
33     r'''^ ([\w.]*\.)?            # class name(s)
34           (\w+)  \s*             # thing name
35           (?: \((.*)\)           # optional: arguments
36            (?:\s* -> \s* (.*))?  #           return annotation
37           )? $                   # and nothing more
38           ''', re.VERBOSE)
39
40
41 def _pseudo_parse_arglist(signode, arglist):
42     """"Parse" a list of arguments separated by commas.
43
44     Arguments can have "optional" annotations given by enclosing them in
45     brackets.  Currently, this will split at any comma, even if it's inside a
46     string literal (e.g. default argument value).
47     """
48     paramlist = addnodes.desc_parameterlist()
49     stack = [paramlist]
50     try:
51         for argument in arglist.split(','):
52             argument = argument.strip()
53             ends_open = ends_close = 0
54             while argument.startswith('['):
55                 stack.append(addnodes.desc_optional())
56                 stack[-2] += stack[-1]
57                 argument = argument[1:].strip()
58             while argument.startswith(']'):
59                 stack.pop()
60                 argument = argument[1:].strip()
61             while argument.endswith(']'):
62                 ends_close += 1
63                 argument = argument[:-1].strip()
64             while argument.endswith('['):
65                 ends_open += 1
66                 argument = argument[:-1].strip()
67             if argument:
68                 stack[-1] += addnodes.desc_parameter(argument, argument, noemph=True)
69             while ends_open:
70                 stack.append(addnodes.desc_optional())
71                 stack[-2] += stack[-1]
72                 ends_open -= 1
73             while ends_close:
74                 stack.pop()
75                 ends_close -= 1
76         if len(stack) != 1:
77             raise IndexError
78     except IndexError:
79         # if there are too few or too many elements on the stack, just give up
80         # and treat the whole argument list as one argument, discarding the
81         # already partially populated paramlist node
82         signode += addnodes.desc_parameterlist()
83         signode[-1] += addnodes.desc_parameter(arglist, arglist)
84     else:
85         signode += paramlist
86
87
88 class OCVPyObject(ObjectDescription):
89     """
90     Description of a general Python object.
91     """
92     option_spec = {
93         'noindex': directives.flag,
94         'module': directives.unchanged,
95     }
96
97     doc_field_types = [
98         TypedField('parameter', label=l_('Parameters'),
99                    names=('param', 'parameter', 'arg', 'argument',
100                           'keyword', 'kwarg', 'kwparam'),
101                    typerolename='obj', typenames=('paramtype', 'type'),
102                    can_collapse=True),
103         TypedField('variable', label=l_('Variables'), rolename='obj',
104                    names=('var', 'ivar', 'cvar'),
105                    typerolename='obj', typenames=('vartype',),
106                    can_collapse=True),
107         GroupedField('exceptions', label=l_('Raises'), rolename='exc',
108                      names=('raises', 'raise', 'exception', 'except'),
109                      can_collapse=True),
110         Field('returnvalue', label=l_('Returns'), has_arg=False,
111               names=('returns', 'return')),
112         Field('returntype', label=l_('Return type'), has_arg=False,
113               names=('rtype',)),
114     ]
115
116     def get_signature_prefix(self, sig):
117         """
118         May return a prefix to put before the object name in the signature.
119         """
120         return ''
121
122     def needs_arglist(self):
123         """
124         May return true if an empty argument list is to be generated even if
125         the document contains none.
126         """
127         return False
128
129     def handle_signature(self, sig, signode):
130         """
131         Transform a Python signature into RST nodes.
132         Returns (fully qualified name of the thing, classname if any).
133
134         If inside a class, the current class name is handled intelligently:
135         * it is stripped from the displayed name if present
136         * it is added to the full name (return value) if not present
137         """
138         signode += nodes.strong("Python:", "Python:")
139         signode += addnodes.desc_name(" ", " ")
140         m = py_sig_re.match(sig)
141         if m is None:
142             raise ValueError
143         name_prefix, name, arglist, retann = m.groups()
144
145         # determine module and class name (if applicable), as well as full name
146         modname = self.options.get(
147             'module', self.env.temp_data.get('py:module'))
148         classname = self.env.temp_data.get('py:class')
149         if classname:
150             add_module = False
151             if name_prefix and name_prefix.startswith(classname):
152                 fullname = name_prefix + name
153                 # class name is given again in the signature
154                 name_prefix = name_prefix[len(classname):].lstrip('.')
155             elif name_prefix:
156                 # class name is given in the signature, but different
157                 # (shouldn't happen)
158                 fullname = classname + '.' + name_prefix + name
159             else:
160                 # class name is not given in the signature
161                 fullname = classname + '.' + name
162         else:
163             add_module = True
164             if name_prefix:
165                 classname = name_prefix.rstrip('.')
166                 fullname = name_prefix + name
167             else:
168                 classname = ''
169                 fullname = name
170
171         signode['module'] = modname
172         signode['class'] = classname
173         signode['fullname'] = fullname
174
175         sig_prefix = self.get_signature_prefix(sig)
176         if sig_prefix:
177             signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
178
179         if name_prefix:
180             signode += addnodes.desc_addname(name_prefix, name_prefix)
181         # exceptions are a special case, since they are documented in the
182         # 'exceptions' module.
183         elif add_module and self.env.config.add_module_names:
184             modname = self.options.get(
185                 'module', self.env.temp_data.get('py:module'))
186             if modname and modname != 'exceptions':
187                 nodetext = modname + '.'
188                 signode += addnodes.desc_addname(nodetext, nodetext)
189
190         signode += addnodes.desc_name(name, name)
191         if not arglist:
192             if self.needs_arglist():
193                 # for callables, add an empty parameter list
194                 signode += addnodes.desc_parameterlist()
195             if retann:
196                 signode += addnodes.desc_returns(retann, retann)
197             return fullname, name_prefix
198         _pseudo_parse_arglist(signode, arglist)
199         if retann:
200             signode += addnodes.desc_returns(retann, retann)
201         return fullname, name_prefix
202
203     def get_index_text(self, modname, name):
204         """
205         Return the text for the index entry of the object.
206         """
207         raise NotImplementedError('must be implemented in subclasses')
208
209     def add_target_and_index(self, name_cls, sig, signode):
210         modname = self.options.get(
211             'module', self.env.temp_data.get('py:module'))
212         fullname = (modname and modname + '.' or '') + name_cls[0]
213         # note target
214         if fullname not in self.state.document.ids:
215             signode['names'].append(fullname)
216             signode['ids'].append(fullname)
217             signode['first'] = (not self.names)
218             self.state.document.note_explicit_target(signode)
219             objects = self.env.domaindata['ocv']['objects']
220             if fullname in objects:
221                 self.env.warn(
222                     self.env.docname,
223                     'duplicate object description of %s, ' % fullname +
224                     'other instance in ' +
225                     self.env.doc2path(objects[fullname][0]) +
226                     ', use :noindex: for one of them',
227                     self.lineno)
228             objects.setdefault(fullname, (self.env.docname, self.objtype, name_cls[0]))
229
230         indextext = self.get_index_text(modname, name_cls)
231         if indextext:
232             self.indexnode['entries'].append(('single', indextext,
233                                               fullname, fullname))
234
235     def before_content(self):
236         # needed for automatic qualification of members (reset in subclasses)
237         self.clsname_set = False
238
239     def after_content(self):
240         if self.clsname_set:
241             self.env.temp_data['py:class'] = None
242
243 class OCVPyModulelevel(OCVPyObject):
244     """
245     Description of an object on module level (functions, data).
246     """
247     directive_prefix = 'py'
248
249     def needs_arglist(self):
250         return self.objtype == self.__class__.directive_prefix + 'function'
251
252     def get_index_text(self, modname, name_cls):
253         if self.objtype == self.__class__.directive_prefix + 'function':
254             if not modname:
255                 fname = name_cls[0]
256                 if not fname.startswith("cv") and not fname.startswith("cv2"):
257                     return _('%s() (Python function)') % fname
258                 pos = fname.find(".")
259                 modname = fname[:pos]
260                 fname = fname[pos+1:]
261                 return _('%s() (Python function in %s)') % (fname, modname)
262             return _('%s() (Python function in %s)') % (name_cls[0], modname)
263         elif self.objtype == 'pydata':
264             if not modname:
265                 return _('%s (Python variable)') % name_cls[0]
266             return _('%s (in module %s)') % (name_cls[0], modname)
267         else:
268             return ''
269
270 class OCVPyOldModulelevel(OCVPyModulelevel):
271     directive_prefix = 'pyold'
272     pass
273
274 class OCVPyXRefRole(XRefRole):
275     def process_link(self, env, refnode, has_explicit_title, title, target):
276         refnode['ocv:module'] = env.temp_data.get('ocv:module')
277         refnode['ocv:class'] = env.temp_data.get('ocv:class')
278         if not has_explicit_title:
279             title = title.lstrip('.')   # only has a meaning for the target
280             target = target.lstrip('~') # only has a meaning for the title
281             # if the first character is a tilde, don't display the module/class
282             # parts of the contents
283             if title[0:1] == '~':
284                 title = title[1:]
285                 dot = title.rfind('.')
286                 if dot != -1:
287                     title = title[dot+1:]
288         # if the first character is a dot, search more specific namespaces first
289         # else search builtins first
290         if target[0:1] == '.':
291             target = target[1:]
292             refnode['refspecific'] = True
293         return title, target
294
295
296 ########################### C/C++/Java Part ###########################
297
298 _identifier_re    = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b)')
299 _argument_name_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b(?:\[\d*\])?|\.\.\.)')
300 _whitespace_re = re.compile(r'\s+(?u)')
301 _string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
302                         r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
303 _visibility_re = re.compile(r'\b(public|private|protected)\b')
304 _operator_re = re.compile(r'''(?x)
305         \[\s*\]
306     |   \(\s*\)
307     |   (<<|>>)=?
308     |   \+\+ | -- | ->\*?
309     |   [!<>=/*%+|&^-]=?
310     |   ~ | && | \| | \|\|
311     |   \,
312 ''')
313
314 _id_shortwords = {
315     'char':                 'c',
316     'signed char':          'c',
317     'unsigned char':        'C',
318     'int':                  'i',
319     'signed int':           'i',
320     'unsigned int':         'U',
321     'long':                 'l',
322     'signed long':          'l',
323     'unsigned long':        'L',
324     'bool':                 'b',
325     'size_t':               's',
326     'std::string':          'ss',
327     'std::ostream':         'os',
328     'std::istream':         'is',
329     'std::iostream':        'ios',
330     'std::vector':          'v',
331     'std::map':             'm',
332     'operator[]':           'subscript-operator',
333     'operator()':           'call-operator',
334     'operator!':            'not-operator',
335     'operator<':            'lt-operator',
336     'operator<=':           'lte-operator',
337     'operator>':            'gt-operator',
338     'operator>=':           'gte-operator',
339     'operator=':            'assign-operator',
340     'operator/':            'div-operator',
341     'operator*':            'mul-operator',
342     'operator%':            'mod-operator',
343     'operator+':            'add-operator',
344     'operator-':            'sub-operator',
345     'operator|':            'or-operator',
346     'operator&':            'and-operator',
347     'operator^':            'xor-operator',
348     'operator&&':           'sand-operator',
349     'operator||':           'sor-operator',
350     'operator==':           'eq-operator',
351     'operator!=':           'neq-operator',
352     'operator<<':           'lshift-operator',
353     'operator>>':           'rshift-operator',
354     'operator-=':           'sub-assign-operator',
355     'operator+=':           'add-assign-operator',
356     'operator*-':           'mul-assign-operator',
357     'operator/=':           'div-assign-operator',
358     'operator%=':           'mod-assign-operator',
359     'operator&=':           'and-assign-operator',
360     'operator|=':           'or-assign-operator',
361     'operator<<=':          'lshift-assign-operator',
362     'operator>>=':          'rshift-assign-operator',
363     'operator^=':           'xor-assign-operator',
364     'operator,':            'comma-operator',
365     'operator->':           'pointer-operator',
366     'operator->*':          'pointer-by-pointer-operator',
367     'operator~':            'inv-operator',
368     'operator++':           'inc-operator',
369     'operator--':           'dec-operator',
370     'operator new':         'new-operator',
371     'operator new[]':       'new-array-operator',
372     'operator delete':      'delete-operator',
373     'operator delete[]':    'delete-array-operator'
374 }
375
376
377 class DefinitionError(Exception):
378
379     def __init__(self, description):
380         self.description = description
381
382     def __unicode__(self):
383         return self.description
384
385     def __str__(self):
386         return unicode(self.encode('utf-8'))
387
388
389 class DefExpr(object):
390
391     def __unicode__(self):
392         raise NotImplementedError()
393
394     def __eq__(self, other):
395         if type(self) is not type(other):
396             return False
397         try:
398             for key, value in self.__dict__.iteritems():
399                 if value != getattr(other, value):
400                     return False
401         except AttributeError:
402             return False
403         return True
404
405     def __ne__(self, other):
406         return not self.__eq__(other)
407
408     def clone(self):
409         """Close a definition expression node"""
410         return deepcopy(self)
411
412     def get_id(self):
413         """Returns the id for the node"""
414         return u''
415
416     def get_name(self):
417         """Returns the name.  Returns either `None` or a node with
418         a name you might call :meth:`split_owner` on.
419         """
420         return None
421
422     def split_owner(self):
423         """Nodes returned by :meth:`get_name` can split off their
424         owning parent.  This function returns the owner and the
425         name as a tuple of two items.  If a node does not support
426         it, it returns None as owner and self as name.
427         """
428         return None, self
429
430     def prefix(self, prefix):
431         """Prefixes a name node (a node returned by :meth:`get_name`)."""
432         raise NotImplementedError()
433
434     def __str__(self):
435         return unicode(self).encode('utf-8')
436
437     def __repr__(self):
438         return '<%s %s>' % (self.__class__.__name__, self)
439
440
441 class PrimaryDefExpr(DefExpr):
442
443     def get_name(self):
444         return self
445
446     def prefix(self, prefix):
447         if isinstance(prefix, PathDefExpr):
448             prefix = prefix.clone()
449             prefix.path.append(self)
450             return prefix
451         return PathDefExpr([prefix, self])
452
453
454 class NameDefExpr(PrimaryDefExpr):
455
456     def __init__(self, name):
457         self.name = name
458
459     def get_id(self):
460         name = _id_shortwords.get(self.name)
461         if name is not None:
462             return name
463         return self.name.replace(u' ', u'-')
464
465     def __unicode__(self):
466         return unicode(self.name)
467
468
469 class PathDefExpr(PrimaryDefExpr):
470
471     def __init__(self, parts):
472         self.path = parts
473
474     def get_id(self):
475         rv = u'::'.join(x.get_id() for x in self.path)
476         return _id_shortwords.get(rv, rv)
477
478     def split_owner(self):
479         if len(self.path) > 1:
480             return PathDefExpr(self.path[:-1]), self.path[-1]
481         return None, self
482
483     def prefix(self, prefix):
484         if isinstance(prefix, PathDefExpr):
485             prefix = prefix.clone()
486             prefix.path.extend(self.path)
487             return prefix
488         return PathDefExpr([prefix] + self.path)
489
490     def __unicode__(self):
491         return u'::'.join(map(unicode, self.path))
492
493
494 class TemplateDefExpr(PrimaryDefExpr):
495
496     def __init__(self, typename, args):
497         self.typename = typename
498         self.args = args
499
500     def split_owner(self):
501         owner, typename = self.typename.split_owner()
502         return owner, TemplateDefExpr(typename, self.args)
503
504     def get_id(self):
505         return u'%s:%s:' % (self.typename.get_id(),
506                             u'.'.join(x.get_id() for x in self.args))
507
508     def __unicode__(self):
509         return u'%s<%s>' % (self.typename, u', '.join(map(unicode, self.args)))
510
511
512 class WrappingDefExpr(DefExpr):
513
514     def __init__(self, typename):
515         self.typename = typename
516
517     def get_name(self):
518         return self.typename.get_name()
519
520
521 class ModifierDefExpr(WrappingDefExpr):
522
523     def __init__(self, typename, modifiers):
524         WrappingDefExpr.__init__(self, typename)
525         self.modifiers = modifiers
526
527     def get_id(self):
528         pieces = [_id_shortwords.get(unicode(x), unicode(x))
529                   for x in self.modifiers]
530         pieces.append(self.typename.get_id())
531         return u'-'.join(pieces)
532
533     def __unicode__(self):
534         return u' '.join(map(unicode, list(self.modifiers) + [self.typename]))
535
536
537 class PtrDefExpr(WrappingDefExpr):
538
539     def get_id(self):
540         return self.typename.get_id() + u'P'
541
542     def __unicode__(self):
543         return u'%s*' % self.typename
544
545
546 class RefDefExpr(WrappingDefExpr):
547
548     def get_id(self):
549         return self.typename.get_id() + u'R'
550
551     def __unicode__(self):
552         return u'%s&' % self.typename
553
554
555 class ConstDefExpr(WrappingDefExpr):
556
557     def __init__(self, typename, prefix=False):
558         WrappingDefExpr.__init__(self, typename)
559         self.prefix = prefix
560
561     def get_id(self):
562         return self.typename.get_id() + u'C'
563
564     def __unicode__(self):
565         return (self.prefix and u'const %s' or u'%s const') % self.typename
566
567 class ConstTemplateDefExpr(WrappingDefExpr):
568
569     def __init__(self, typename, prefix=False):
570         WrappingDefExpr.__init__(self, typename)
571         self.prefix = prefix
572
573     def get_id(self):
574         return self.typename.get_id() + u'C'
575
576     def __unicode__(self):
577         return (self.prefix and u'const %s' or u'%s const') % self.typename
578
579
580 class CastOpDefExpr(PrimaryDefExpr):
581
582     def __init__(self, typename):
583         self.typename = typename
584
585     def get_id(self):
586         return u'castto-%s-operator' % self.typename.get_id()
587
588     def __unicode__(self):
589         return u'operator %s' % self.typename
590
591
592 class ArgumentDefExpr(DefExpr):
593
594     def __init__(self, type, name, default=None):
595         self.name = name
596         self.type = type
597         self.default = default
598
599     def get_name(self):
600         return self.name.get_name()
601
602     def get_id(self):
603         if self.type is None:
604             return 'X'
605         return self.type.get_id()
606
607     def __unicode__(self):
608         return (u'%s %s' % (self.type or u'', self.name or u'')).strip() + \
609                (self.default is not None and u'=%s' % self.default or u'')
610
611
612 class NamedDefExpr(DefExpr):
613
614     def __init__(self, name, visibility, static):
615         self.name = name
616         self.visibility = visibility
617         self.static = static
618
619     def get_name(self):
620         return self.name.get_name()
621
622     def get_modifiers(self):
623         rv = []
624         if self.visibility != 'public':
625             rv.append(self.visibility)
626         if self.static:
627             rv.append(u'static')
628         return rv
629
630
631 class TypeObjDefExpr(NamedDefExpr):
632
633     def __init__(self, name, visibility, static, typename):
634         NamedDefExpr.__init__(self, name, visibility, static)
635         self.typename = typename
636
637     def get_id(self):
638         if self.typename is None:
639             return self.name.get_id()
640         return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
641
642     def __unicode__(self):
643         buf = self.get_modifiers()
644         if self.typename is None:
645             buf.append(unicode(self.name))
646         else:
647             buf.extend(map(unicode, (self.typename, self.name)))
648         return u' '.join(buf)
649
650
651 class MemberObjDefExpr(NamedDefExpr):
652
653     def __init__(self, name, visibility, static, typename, value):
654         NamedDefExpr.__init__(self, name, visibility, static)
655         self.typename = typename
656         self.value = value
657
658     def get_id(self):
659         return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
660
661     def __unicode__(self):
662         buf = self.get_modifiers()
663         buf.append(u'%s %s' % (self.typename, self.name))
664         if self.value is not None:
665             buf.append(u'= %s' % self.value)
666         return u' '.join(buf)
667
668
669 class FuncDefExpr(NamedDefExpr):
670
671     def __init__(self, name, visibility, static, explicit, rv,
672                  signature, const, pure_virtual, virtual):
673         NamedDefExpr.__init__(self, name, visibility, static)
674         self.rv = rv
675         self.signature = signature
676         self.explicit = explicit
677         self.const = const
678         self.pure_virtual = pure_virtual
679         self.virtual = virtual
680
681     def get_id(self):
682         return u'%s%s%s' % (
683             self.name.get_id(),
684             self.signature and u'__' +
685                 u'.'.join(x.get_id() for x in self.signature) or u'',
686             self.const and u'C' or u''
687         )
688
689     def __unicode__(self):
690         buf = self.get_modifiers()
691         if self.explicit:
692             buf.append(u'explicit')
693         if self.virtual:
694             buf.append(u'virtual')
695         if self.rv is not None:
696             buf.append(unicode(self.rv))
697         buf.append(u'%s(%s)' % (self.name, u', '.join(
698             map(unicode, self.signature))))
699         if self.const:
700             buf.append(u'const')
701         if self.pure_virtual:
702             buf.append(u'= 0')
703         return u' '.join(buf)
704
705
706 class ClassDefExpr(NamedDefExpr):
707
708     def __init__(self, name, visibility, static, parents = None):
709         NamedDefExpr.__init__(self, name, visibility, static)
710         self.parents = parents
711
712     def get_id(self):
713         return self.name.get_id()
714
715     def __unicode__(self):
716         buf = self.get_modifiers()
717         buf.append(unicode(self.name))
718         return u' '.join(buf)
719
720
721 class DefinitionParser(object):
722
723     # mapping of valid type modifiers.  if the set is None it means
724     # the modifier can prefix all types, otherwise only the types
725     # (actually more keywords) in the set.  Also check
726     # _guess_typename when changing this.
727     _modifiers = {
728         'volatile':     None,
729         'register':     None,
730         'mutable':      None,
731         'const':        None,
732         'typename':     None,
733         'unsigned':     set(('char', 'short', 'int', 'long')),
734         'signed':       set(('char', 'short', 'int', 'long')),
735         'short':        set(('int',)),
736         'long':         set(('int', 'long', 'double'))
737     }
738
739     def __init__(self, definition):
740         self.definition = definition.strip()
741         self.pos = 0
742         self.end = len(self.definition)
743         self.last_match = None
744         self._previous_state = (0, None)
745
746     def fail(self, msg):
747         raise DefinitionError('Invalid definition: %s [error at %d]\n  %s' %
748             (msg, self.pos, self.definition))
749
750     def match(self, regex):
751         match = regex.match(self.definition, self.pos)
752         if match is not None:
753             self._previous_state = (self.pos, self.last_match)
754             self.pos = match.end()
755             self.last_match = match
756             return True
757         return False
758
759     def backout(self):
760         self.pos, self.last_match = self._previous_state
761
762     def skip_string(self, string):
763         strlen = len(string)
764         if self.definition[self.pos:self.pos + strlen] == string:
765             self.pos += strlen
766             return True
767         return False
768
769     def skip_word(self, word):
770         return self.match(re.compile(r'\b%s\b' % re.escape(word)))
771
772     def skip_ws(self):
773         return self.match(_whitespace_re)
774
775     @property
776     def eof(self):
777         return self.pos >= self.end
778
779     @property
780     def current_char(self):
781         try:
782             return self.definition[self.pos]
783         except IndexError:
784             return 'EOF'
785
786     @property
787     def matched_text(self):
788         if self.last_match is not None:
789             return self.last_match.group()
790
791     def _parse_operator(self):
792         self.skip_ws()
793         # thank god, a regular operator definition
794         if self.match(_operator_re):
795             return NameDefExpr('operator' +
796                                 _whitespace_re.sub('', self.matched_text))
797         # new/delete operator?
798         for allocop in 'new', 'delete':
799             if not self.skip_word(allocop):
800                 continue
801             self.skip_ws()
802             if self.skip_string('['):
803                 self.skip_ws()
804                 if not self.skip_string(']'):
805                     self.fail('expected "]" for ' + allocop)
806                 allocop += '[]'
807             return NameDefExpr('operator ' + allocop)
808
809         # oh well, looks like a cast operator definition.
810         # In that case, eat another type.
811         type = self._parse_type()
812         return CastOpDefExpr(type)
813
814     def _parse_name(self):
815         if not self.match(_argument_name_re):
816             self.fail('expected name')
817         identifier = self.matched_text
818
819         # strictly speaking, operators are not regular identifiers
820         # but because operator is a keyword, it might not be used
821         # for variable names anyways, so we can safely parse the
822         # operator here as identifier
823         if identifier == 'operator':
824             return self._parse_operator()
825
826         return NameDefExpr(identifier)
827
828     def _guess_typename(self, path):
829         if not path:
830             return [], 'int'
831         # for the long type, we don't want the int in there
832         if 'long' in path:
833             path = [x for x in path if x != 'int']
834             # remove one long
835             path.remove('long')
836             return path, 'long'
837         if path[-1] in ('int', 'char'):
838             return path[:-1], path[-1]
839         return path, 'int'
840
841     def _attach_crefptr(self, expr, is_const=False):
842         if is_const:
843             expr = ConstDefExpr(expr, prefix=True)
844         while 1:
845             self.skip_ws()
846             if self.skip_word('const'):
847                 expr = ConstDefExpr(expr)
848             elif self.skip_string('*'):
849                 expr = PtrDefExpr(expr)
850             elif self.skip_string('&'):
851                 expr = RefDefExpr(expr)
852             else:
853                 return expr
854
855     def _peek_const(self, path):
856         try:
857             path.remove('const')
858             return True
859         except ValueError:
860             return False
861
862     def _parse_builtin(self, modifier):
863         path = [modifier]
864         following = self._modifiers[modifier]
865         while 1:
866             self.skip_ws()
867             if not self.match(_identifier_re):
868                 break
869             identifier = self.matched_text
870             if identifier in following:
871                 path.append(identifier)
872                 following = self._modifiers[modifier]
873                 assert following
874             else:
875                 self.backout()
876                 break
877
878         is_const = self._peek_const(path)
879         modifiers, typename = self._guess_typename(path)
880         rv = ModifierDefExpr(NameDefExpr(typename), modifiers)
881         return self._attach_crefptr(rv, is_const)
882
883     def _parse_type_expr(self):
884         typename = self._parse_name()
885         if typename and self.skip_string('['):
886             typename.name += '['
887             if self.match(re.compile(r'\d*')):
888                 typename.name += self.last_match.group(0)
889             typename.name += ']'
890             if not self.skip_string(']'):
891                 self.fail('expected type')
892         self.skip_ws()
893         if not self.skip_string('<'):
894             return typename
895
896         args = []
897         while 1:
898             self.skip_ws()
899             if self.skip_string('>'):
900                 break
901             if args:
902                 if not self.skip_string(','):
903                     self.fail('"," or ">" in template expected')
904                 self.skip_ws()
905             args.append(self._parse_type(True))
906         return TemplateDefExpr(typename, args)
907
908     def _parse_type(self, in_template=False):
909         self.skip_ws()
910         result = []
911         modifiers = []
912
913         if self.match(re.compile(r'template\w*<([^>]*)>')):
914             args = self.last_match.group(1).split(',')
915             args = [a.strip() for a in args]
916             modifiers.append(TemplateDefExpr('template', args))
917
918         # if there is a leading :: or not, we don't care because we
919         # treat them exactly the same.  Buf *if* there is one, we
920         # don't have to check for type modifiers
921         if not self.skip_string('::'):
922             self.skip_ws()
923             while self.match(_identifier_re):
924                 modifier = self.matched_text
925                 if modifier in self._modifiers:
926                     following = self._modifiers[modifier]
927                     # if the set is not none, there is a limited set
928                     # of types that might follow.  It is technically
929                     # impossible for a template to follow, so what
930                     # we do is go to a different function that just
931                     # eats types
932                     if following is not None:
933                         return self._parse_builtin(modifier)
934                     modifiers.append(modifier)
935                 else:
936                     self.backout()
937                     break
938
939         while 1:
940             self.skip_ws()
941             if (in_template and self.current_char in ',>') or \
942                (result and not self.skip_string('::')) or \
943                self.eof:
944                 break
945             result.append(self._parse_type_expr())
946
947         if not result:
948             self.fail('expected type')
949         if len(result) == 1:
950             rv = result[0]
951         else:
952             rv = PathDefExpr(result)
953         is_const = self._peek_const(modifiers)
954         if is_const:
955             rv = ConstDefExpr(rv, prefix=True)
956         if modifiers:
957             rv = ModifierDefExpr(rv, modifiers)
958         return self._attach_crefptr(rv, False)
959
960     def _parse_default_expr(self):
961         self.skip_ws()
962         if self.match(_string_re):
963             return self.matched_text
964         paren_stack_depth = 0
965         max_pos = len(self.definition)
966         rv_start = self.pos
967         while 1:
968             idx0 = self.definition.find('(', self.pos)
969             idx1 = self.definition.find(',', self.pos)
970             idx2 = self.definition.find(')', self.pos)
971             if idx0 < 0:
972                 idx0 = max_pos
973             if idx1 < 0:
974                 idx1 = max_pos
975             if idx2 < 0:
976                 idx2 = max_pos
977             idx = min(idx0, idx1, idx2)
978             if idx >= max_pos:
979                 self.fail('unexpected end in default expression')
980             if idx == idx0:
981                 paren_stack_depth += 1
982             elif idx == idx2:
983                 paren_stack_depth -= 1
984                 if paren_stack_depth < 0:
985                     break
986             elif paren_stack_depth == 0:
987                 break
988             self.pos = idx+1
989
990         rv = self.definition[rv_start:idx]
991         self.pos = idx
992         return rv
993
994     def _parse_signature(self):
995         if r'CvStatModel::train' in self.definition:
996             # hack to skip parsing of problematic definition
997             self.pos = self.end
998             return [ArgumentDefExpr("const Mat&", "train_data", None), ArgumentDefExpr(None, self.definition[self.definition.find("["):-1], None)], False, True
999
1000         self.skip_ws()
1001         if not self.skip_string('('):
1002             self.fail('expected parentheses for function')
1003
1004         args = []
1005         while 1:
1006             self.skip_ws()
1007             if self.eof:
1008                 self.fail('missing closing parentheses')
1009             if self.skip_string(')'):
1010                 break
1011             if args:
1012                 if not self.skip_string(','):
1013                     self.fail('expected comma between arguments')
1014                 self.skip_ws()
1015
1016             argtype = self._parse_type()
1017             self.skip_ws()
1018             if unicode(argtype) == u"...":
1019                 if not self.skip_string(')'):
1020                     self.fail("var arg must be the last argument")
1021                 args.append(ArgumentDefExpr(None, argtype, None))
1022                 break
1023             argname = default = None
1024             if self.skip_string('='):
1025                 self.pos += 1
1026                 default = self._parse_default_expr()
1027             elif self.current_char not in ',)':
1028                 argname = self._parse_name()
1029                 self.skip_ws()
1030                 if self.skip_string('='):
1031                     default = self._parse_default_expr()
1032
1033             args.append(ArgumentDefExpr(argtype, argname, default))
1034         self.skip_ws()
1035         const = self.skip_word('const')
1036         if const:
1037             self.skip_ws()
1038         if self.skip_string('='):
1039             self.skip_ws()
1040             if not (self.skip_string('0') or \
1041                     self.skip_word('NULL') or \
1042                     self.skip_word('nullptr')):
1043                 self.fail('pure virtual functions must be defined with '
1044                           'either 0, NULL or nullptr, other macros are '
1045                           'not allowed')
1046             pure_virtual = True
1047         else:
1048             pure_virtual = False
1049         return args, const, pure_virtual
1050
1051     def _parse_visibility_static(self):
1052         visibility =  'public'
1053         if self.match(_visibility_re):
1054             visibility = self.matched_text
1055         static = self.skip_word('static')
1056         return visibility, static
1057
1058     def parse_type(self):
1059         return self._parse_type()
1060
1061     def parse_type_object(self):
1062         visibility, static = self._parse_visibility_static()
1063         typename = self._parse_type()
1064         self.skip_ws()
1065         if not self.eof:
1066             name = self._parse_type()
1067         else:
1068             name = typename
1069             typename = None
1070         return TypeObjDefExpr(name, visibility, static, typename)
1071
1072     def parse_member_object(self):
1073         visibility, static = self._parse_visibility_static()
1074         typename = self._parse_type()
1075         name = self._parse_type()
1076         self.skip_ws()
1077         if self.skip_string('='):
1078             value = self.read_rest().strip()
1079         else:
1080             value = None
1081         return MemberObjDefExpr(name, visibility, static, typename, value)
1082
1083     def parse_enum_member_object(self):
1084         visibility, static = self._parse_visibility_static()
1085         typename = None
1086         name = self._parse_type()
1087         self.skip_ws()
1088         if self.skip_string('='):
1089             value = self.read_rest().strip()
1090         else:
1091             value = None
1092         return MemberObjDefExpr(name, visibility, static, typename, value)
1093
1094     def parse_function(self):
1095         visibility, static = self._parse_visibility_static()
1096         if self.skip_word('explicit'):
1097             explicit = True
1098             self.skip_ws()
1099         else:
1100             explicit = False
1101         if self.skip_word('virtual'):
1102             virtual = True
1103             self.skip_ws()
1104         else:
1105             virtual = False
1106         rv = self._parse_type()
1107         self.skip_ws()
1108         # some things just don't have return values
1109         if self.current_char == '(':
1110             name = rv
1111             rv = None
1112         else:
1113             name = self._parse_type()
1114         return FuncDefExpr(name, visibility, static, explicit,  rv,
1115                            *self._parse_signature(), virtual = virtual)
1116
1117     def parse_class(self):
1118         visibility, static = self._parse_visibility_static()
1119         typename = self._parse_type()
1120         parent = None
1121         self.skip_ws()
1122         parents = []
1123         if self.skip_string(':'):
1124             while not self.eof:
1125                 self.skip_ws()
1126                 classname_pos = self.pos
1127                 pvisibility, pstatic = self._parse_visibility_static()
1128                 if pstatic:
1129                     self.fail('unsepected static keyword, got %r' %
1130                           self.definition[self.classname_pos:])
1131                 parents.append(ClassDefExpr(self._parse_type(), pvisibility, pstatic))
1132                 if not self.skip_string(','):
1133                     break
1134         return ClassDefExpr(typename, visibility, static, parents)
1135
1136     def read_rest(self):
1137         rv = self.definition[self.pos:]
1138         self.pos = self.end
1139         return rv
1140
1141     def assert_end(self):
1142         self.skip_ws()
1143         if not self.eof:
1144             self.fail('expected end of definition, got %r' %
1145                       self.definition[self.pos:])
1146
1147
1148 class OCVObject(ObjectDescription):
1149     """Description of a C++ language object."""
1150
1151     langname = "C++"
1152     ismember = False
1153
1154     doc_field_types = [
1155         TypedField('parameter', label=l_('Parameters'),
1156                    names=('param', 'parameter', 'arg', 'argument'),
1157                    typerolename='type', typenames=('type',)),
1158         Field('returnvalue', label=l_('Returns'), has_arg=False,
1159               names=('returns', 'return')),
1160         Field('returntype', label=l_('Return type'), has_arg=False,
1161               names=('rtype',)),
1162     ]
1163
1164     def attach_name(self, node, name):
1165         owner, name = name.split_owner()
1166         varname = unicode(name)
1167         if owner is not None:
1168             owner = unicode(owner) + '::'
1169             node += addnodes.desc_addname(owner, owner)
1170         node += addnodes.desc_name(varname, varname)
1171
1172     def attach_type(self, node, type):
1173         # XXX: link to c?
1174         text = unicode(type)
1175         pnode = addnodes.pending_xref(
1176             '', refdomain='ocv', reftype='type',
1177             reftarget=text, modname=None, classname=None)
1178         pnode['ocv:parent'] = self.env.temp_data.get('ocv:parent')
1179         pnode += nodes.Text(text)
1180         node += pnode
1181
1182     def attach_modifiers(self, node, obj):
1183         if not self.__class__.ismember:
1184             lname = self.__class__.langname
1185             node += nodes.strong(lname + ":", lname + ":")
1186             node += addnodes.desc_name(" ", " ")
1187
1188         if obj.visibility != 'public':
1189             node += addnodes.desc_annotation(obj.visibility,
1190                                              obj.visibility)
1191             node += nodes.Text(' ')
1192         if obj.static:
1193             node += addnodes.desc_annotation('static', 'static')
1194             node += nodes.Text(' ')
1195
1196     def add_target_and_index(self, sigobj, sig, signode):
1197         theid = sig#obj.get_id()
1198         theid = re.sub(r" +", " ", theid)
1199         if self.objtype == 'emember':
1200             theid = re.sub(r" ?=.*", "", theid)
1201         theid = re.sub(r"=[^,()]+\([^)]*?\)[^,)]*(,|\))", "\\1", theid)
1202         theid = re.sub(r"=\w*[^,)(]+(,|\))", "\\1", theid)
1203         theid = theid.replace("( ", "(").replace(" )", ")")
1204         name = unicode(sigobj.name)
1205         if theid not in self.state.document.ids:
1206             signode['names'].append(theid)
1207             signode['ids'].append(theid)
1208             signode['first'] = (not self.names)
1209             self.state.document.note_explicit_target(signode)
1210
1211             #self.env.domaindata['ocv']['objects'].setdefault(name,
1212                 #(self.env.docname, self.objtype, theid))
1213             self.env.domaindata['ocv']['objects'].setdefault(theid,
1214                 (self.env.docname, self.objtype, theid))
1215             self.env.domaindata['ocv']['objects2'].setdefault(name,
1216                 (self.env.docname, self.objtype, theid))
1217
1218         indextext = self.get_index_text(name)
1219         if indextext:
1220             self.indexnode['entries'].append(('single', indextext, theid, name))
1221
1222     def before_content(self):
1223         lastname = self.names and self.names[-1]
1224         if lastname and not self.env.temp_data.get('ocv:parent'):
1225             assert isinstance(lastname, NamedDefExpr)
1226             self.env.temp_data['ocv:parent'] = lastname.name
1227             self.parentname_set = True
1228         else:
1229             self.parentname_set = False
1230
1231     def after_content(self):
1232         if self.parentname_set:
1233             self.env.temp_data['ocv:parent'] = None
1234
1235     def parse_definition(self, parser):
1236         raise NotImplementedError()
1237
1238     def describe_signature(self, signode, arg):
1239         raise NotImplementedError()
1240
1241     def handle_signature(self, sig, signode):
1242         parser = DefinitionParser(sig)
1243         try:
1244             rv = self.parse_definition(parser)
1245             parser.assert_end()
1246         except DefinitionError, e:
1247             self.env.warn(self.env.docname,
1248                           e.description, self.lineno)
1249             raise ValueError
1250         self.describe_signature(signode, rv)
1251
1252         parent = self.env.temp_data.get('ocv:parent')
1253         if parent is not None:
1254             rv = rv.clone()
1255             rv.name = rv.name.prefix(parent)
1256         return rv
1257
1258
1259 class OCVClassObject(OCVObject):
1260     object_annotation = "class "
1261     object_long_name = "class"
1262
1263     def attach_modifiers(self, node, obj, skip_visibility = 'public'):
1264         if obj.visibility != skip_visibility:
1265             node += addnodes.desc_annotation(obj.visibility,
1266                                              obj.visibility)
1267             node += nodes.Text(' ')
1268         if obj.static:
1269             node += addnodes.desc_annotation('static', 'static')
1270             node += nodes.Text(' ')
1271
1272     def get_index_text(self, name):
1273         return _('%s (C++ %s)') % (name, self.__class__.object_long_name)
1274
1275     def parse_definition(self, parser):
1276         return parser.parse_class()
1277
1278     def describe_signature(self, signode, cls):
1279         self.attach_modifiers(signode, cls)
1280         signode += addnodes.desc_annotation(self.__class__.object_annotation, self.__class__.object_annotation)
1281         self.attach_name(signode, cls.name)
1282         first_parent = True
1283         for p in cls.parents:
1284             if first_parent:
1285                 signode += nodes.Text(' : ')
1286                 first_parent = False
1287             else:
1288                 signode += nodes.Text(', ')
1289             self.attach_modifiers(signode, p, None)
1290             self.attach_name(signode, p.name)
1291
1292 class OCVStructObject(OCVClassObject):
1293     object_annotation = "struct "
1294     object_long_name = "structure"
1295
1296 class OCVTypeObject(OCVObject):
1297
1298     def get_index_text(self, name):
1299         if self.objtype == 'type':
1300             return _('%s (C++ type)') % name
1301         return ''
1302
1303     def parse_definition(self, parser):
1304         return parser.parse_type_object()
1305
1306     def describe_signature(self, signode, obj):
1307         self.attach_modifiers(signode, obj)
1308         signode += addnodes.desc_annotation('type ', 'type ')
1309         if obj.typename is not None:
1310             self.attach_type(signode, obj.typename)
1311             signode += nodes.Text(' ')
1312         self.attach_name(signode, obj.name)
1313
1314 class OCVEnumObject(OCVObject):
1315
1316     def get_index_text(self, name):
1317         if self.objtype == 'enum':
1318             return _('%s (enum)') % name
1319         return ''
1320
1321     def parse_definition(self, parser):
1322         return parser.parse_type_object()
1323
1324     def describe_signature(self, signode, obj):
1325         self.attach_modifiers(signode, obj)
1326         signode += addnodes.desc_annotation('enum ', 'enum ')
1327         if obj.typename is not None:
1328             self.attach_type(signode, obj.typename)
1329             signode += nodes.Text(' ')
1330         self.attach_name(signode, obj.name)
1331
1332
1333 class OCVMemberObject(OCVObject):
1334     ismember = True
1335
1336     def get_index_text(self, name):
1337         if self.objtype == 'member':
1338             return _('%s (C++ member)') % name
1339         return ''
1340
1341     def parse_definition(self, parser):
1342         parent_class = self.env.temp_data.get('ocv:parent')
1343         if parent_class is None:
1344             parser.fail("missing parent structure/class")
1345         return parser.parse_member_object()
1346
1347     def describe_signature(self, signode, obj):
1348         self.attach_modifiers(signode, obj)
1349         if obj.typename:
1350             self.attach_type(signode, obj.typename)
1351             signode += nodes.Text(' ')
1352         self.attach_name(signode, obj.name)
1353         if obj.value is not None:
1354             signode += nodes.Text(u' = ' + obj.value)
1355
1356 class OCVEnumMemberObject(OCVMemberObject):
1357     def parse_definition(self, parser):
1358         # parent_class = self.env.temp_data.get('ocv:parent')
1359         # if parent_class is None:
1360         #     parser.fail("missing parent structure/class")
1361         return parser.parse_enum_member_object()
1362
1363 class OCVFunctionObject(OCVObject):
1364
1365     def attach_function(self, node, func):
1366         owner, name = func.name.split_owner()
1367         if owner is not None:
1368             owner = unicode(owner) + '::'
1369             node += addnodes.desc_addname(owner, owner)
1370
1371         # cast operator is special.  in this case the return value
1372         # is reversed.
1373         if isinstance(name, CastOpDefExpr):
1374             node += addnodes.desc_name('operator', 'operator')
1375             node += nodes.Text(u' ')
1376             self.attach_type(node, name.typename)
1377         else:
1378             funcname = unicode(name)
1379             node += addnodes.desc_name(funcname, funcname)
1380
1381         paramlist = addnodes.desc_parameterlist()
1382         for arg in func.signature:
1383             param = addnodes.desc_parameter('', '', noemph=True)
1384             if arg.type is not None:
1385                 self.attach_type(param, arg.type)
1386                 param += nodes.Text(u' ')
1387             #param += nodes.emphasis(unicode(arg.name), unicode(arg.name))
1388             sbrIdx = unicode(arg.name).find("[")
1389             if sbrIdx < 0:
1390                 param += nodes.strong(unicode(arg.name), unicode(arg.name))
1391             else:
1392                 param += nodes.strong(unicode(arg.name)[:sbrIdx], unicode(arg.name)[:sbrIdx])
1393                 param += nodes.Text(unicode(arg.name)[sbrIdx:])
1394             if arg.default is not None:
1395                 def_ = u'=' + unicode(arg.default)
1396                 #param += nodes.emphasis(def_, def_)
1397                 param += nodes.Text(def_)
1398             paramlist += param
1399
1400         node += paramlist
1401         if func.const:
1402             node += addnodes.desc_addname(' const', ' const')
1403         if func.pure_virtual:
1404             node += addnodes.desc_addname(' = 0', ' = 0')
1405
1406     def get_index_text(self, name):
1407         lname = self.__class__.langname
1408         if lname == "C" and name.startswith("cv"):
1409             name = name[2:]
1410         return _('%s (%s function)') % (name, lname)
1411
1412     def parse_definition(self, parser):
1413         return parser.parse_function()
1414
1415     def describe_signature(self, signode, func):
1416         self.attach_modifiers(signode, func)
1417         if func.explicit:
1418             signode += addnodes.desc_annotation('explicit', 'explicit')
1419             signode += nodes.Text(' ')
1420         if func.virtual:
1421             signode += addnodes.desc_annotation('virtual', 'virtual')
1422             signode += nodes.Text(' ')
1423         # return value is None for things with a reverse return value
1424         # such as casting operator definitions or constructors
1425         # and destructors.
1426         if func.rv is not None:
1427             self.attach_type(signode, func.rv)
1428         signode += nodes.Text(u' ')
1429         self.attach_function(signode, func)
1430
1431
1432 class OCVCurrentNamespace(Directive):
1433     """This directive is just to tell Sphinx that we're documenting
1434     stuff in namespace foo.
1435     """
1436
1437     has_content = False
1438     required_arguments = 1
1439     optional_arguments = 0
1440     final_argument_whitespace = True
1441     option_spec = {}
1442
1443     def run(self):
1444         env = self.state.document.settings.env
1445         if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
1446             env.temp_data['ocv:prefix'] = None
1447         else:
1448             parser = DefinitionParser(self.arguments[0])
1449             try:
1450                 prefix = parser.parse_type()
1451                 parser.assert_end()
1452             except DefinitionError, e:
1453                 self.env.warn(self.env.docname,
1454                               e.description, self.lineno)
1455             else:
1456                 env.temp_data['ocv:prefix'] = prefix
1457         return []
1458
1459
1460 class OCVXRefRole(XRefRole):
1461
1462     def process_link(self, env, refnode, has_explicit_title, title, target):
1463         refnode['ocv:parent'] = env.temp_data.get('ocv:parent')
1464         if not has_explicit_title:
1465             target = target.lstrip('~') # only has a meaning for the title
1466             # if the first character is a tilde, don't display the module/class
1467             # parts of the contents
1468             if title[:1] == '~':
1469                 title = title[1:]
1470                 dcolon = title.rfind('::')
1471                 if dcolon != -1:
1472                     title = title[dcolon + 2:]
1473         return title, target
1474
1475
1476 class OCVCFunctionObject(OCVFunctionObject):
1477     langname = "C"
1478
1479 class OCVJavaFunctionObject(OCVFunctionObject):
1480     langname = "Java"
1481
1482
1483 class OCVDomain(Domain):
1484     """OpenCV C++ language domain."""
1485     name = 'ocv'
1486     label = 'C++'
1487     object_types = {
1488         'class':    ObjType(l_('class'),    'class'),
1489         'struct':    ObjType(l_('struct'),    'struct'),
1490         'function': ObjType(l_('function'), 'func', 'funcx'),
1491         'cfunction': ObjType(l_('cfunction'), 'cfunc', 'cfuncx'),
1492         'jfunction': ObjType(l_('jfunction'), 'jfunc', 'jfuncx'),
1493         'pyfunction': ObjType(l_('pyfunction'), 'pyfunc'),
1494         'pyoldfunction': ObjType(l_('pyoldfunction'), 'pyoldfunc'),
1495         'member':   ObjType(l_('member'),   'member'),
1496         'emember':   ObjType(l_('emember'),   'emember'),
1497         'type':     ObjType(l_('type'),     'type'),
1498         'enum':     ObjType(l_('enum'),     'enum')
1499     }
1500
1501     directives = {
1502         'class':        OCVClassObject,
1503         'struct':       OCVStructObject,
1504         'function':     OCVFunctionObject,
1505         'cfunction':    OCVCFunctionObject,
1506         'jfunction':    OCVJavaFunctionObject,
1507         'pyfunction':   OCVPyModulelevel,
1508         'pyoldfunction':   OCVPyOldModulelevel,
1509         'member':       OCVMemberObject,
1510         'emember':      OCVEnumMemberObject,
1511         'type':         OCVTypeObject,
1512         'enum':         OCVEnumObject,
1513         'namespace':    OCVCurrentNamespace
1514     }
1515     roles = {
1516         'class':  OCVXRefRole(),
1517         'struct':  OCVXRefRole(),
1518         'func' :  OCVXRefRole(fix_parens=True),
1519         'funcx' :  OCVXRefRole(),
1520         'cfunc' :  OCVXRefRole(fix_parens=True),
1521         'cfuncx' :  OCVXRefRole(),
1522         'jfunc' :  OCVXRefRole(fix_parens=True),
1523         'jfuncx' :  OCVXRefRole(),
1524         'pyfunc' :  OCVPyXRefRole(),
1525         'pyoldfunc' :  OCVPyXRefRole(),
1526         'member': OCVXRefRole(),
1527         'emember': OCVXRefRole(),
1528         'type':   OCVXRefRole(),
1529         'enum':   OCVXRefRole()
1530     }
1531     initial_data = {
1532         'objects': {},  # fullname -> docname, objtype
1533     }
1534
1535     def __init__(self, env):
1536         Domain.__init__(self, env)
1537         self.data['objects2'] = {}
1538
1539     def clear_doc(self, docname):
1540         for fullname, (fn, _, _) in self.data['objects'].items():
1541             if fn == docname:
1542                 del self.data['objects'][fullname]
1543
1544     def resolve_xref(self, env, fromdocname, builder,
1545                      typ, target, node, contnode):
1546         def _create_refnode(expr):
1547             name = unicode(expr)
1548             if "type" in self.objtypes_for_role(typ):
1549                 return None
1550             if "cfunction" in self.objtypes_for_role(typ):
1551                 if not name.startswith(u'cv'):
1552                     name = u'cv' + name
1553             dict = self.data['objects']
1554             if name not in dict:
1555                 dict = self.data['objects2']
1556             if name not in dict:
1557                 refdoc = node.get('refdoc', fromdocname)
1558                 env.warn(refdoc, 'unresolved reference: %r - %r' % (target, typ), node.line)
1559                 return None
1560             obj = dict[name]
1561             if obj[1] not in self.objtypes_for_role(typ):
1562                 return None
1563             title = obj[2]
1564             if "class" in self.objtypes_for_role(typ):
1565                 title = u"class " + title
1566             elif "struct" in self.objtypes_for_role(typ):
1567                 title = u"struct " + title
1568             return make_refnode(builder, fromdocname, obj[0], obj[2],
1569                                 contnode, title)
1570
1571         parser = DefinitionParser(target)
1572         try:
1573             expr = parser.parse_type().get_name()
1574             parser.skip_ws()
1575             if not parser.eof or expr is None:
1576                 raise DefinitionError('')
1577         except DefinitionError:
1578             refdoc = node.get('refdoc', fromdocname)
1579             env.warn(refdoc, 'unparseable C++ definition: %r' % target,
1580                      node.line)
1581             return None
1582
1583         parent = node['ocv:parent']
1584
1585         rv = _create_refnode(expr)
1586         if rv is not None or parent is None:
1587             return rv
1588         parent = parent.get_name()
1589
1590         rv = _create_refnode(expr.prefix(parent))
1591         if rv is not None:
1592             return rv
1593
1594         parent, name = parent.split_owner()
1595         return _create_refnode(expr.prefix(parent))
1596
1597     def get_objects(self):
1598         for refname, (docname, type, theid) in self.data['objects'].iteritems():
1599             yield (refname, refname, type, docname, refname, 1)
1600
1601     def get_type_name(self, type, primary=False):
1602         """
1603         Return full name for given ObjType.
1604         """
1605         if primary:
1606             return type.lname
1607
1608         return {
1609             'class':         _('C++ class'),
1610             'struct':        _('C/C++ struct'),
1611             'function':      _('C++ function'),
1612             'cfunction':     _('C function'),
1613             'jfunction':     _('Java method'),
1614             'pyfunction':    _('Python function'),
1615             'pyoldfunction': _('Legacy Python function'),
1616             'member':        _('C++ member'),
1617             'emember':       _('enum member'),
1618             'type':          _('C/C++ type'),
1619             'enum':          _('C/C++ enum'),
1620             'namespace':     _('C++ namespace'),
1621             }.get(type.lname, _('%s %s') % (self.label, type.lname))
1622
1623 def setup(app):
1624     app.add_domain(OCVDomain)