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