def _parseAttributes(self): index = 0 exploded = self.attributes.split(',') # attributes defined by a single letter. __singleLetters = { 'C': ('accessMethod', 'copy'), '&': ('accessMethod', 'retain'), 'N': ('atomic', False), 'D': ('synthesizedIvar', ''), 'P': ('gcStrength', '__strong'), 'W': ('gcStrength', '__weak'), 'G': ('hasGetter', True), 'S': ('hasSetter', True), 'R': ('readOnly', True) } # attributes defined by a letter followed by some strings. __multiLetters = { 'G': 'getter', 'S': 'setter', 'V': 'synthesizedIvar' } buffer = [] for string in exploded: if buffer: buffer.append(string) else: typ = string[0] if typ in __multiLetters: setattr(self, __multiLetters[typ], string[1:]) if typ in __singleLetters: (attr, val) = __singleLetters[typ] setattr(self, attr, val) if typ == 'T': buffer = [string[1:]] if buffer: joinedBuffer = ','.join(buffer) joinedBufferLength = len(joinedBuffer) if balancedSubstring(joinedBuffer) <= joinedBufferLength: self.encoding = joinedBuffer buffer = []
def _parseAttributes(self): index = 0 exploded = self.attributes.split(',') # attributes defined by a single letter. __singleLetters = { 'C': ('accessMethod', 'copy'), '&': ('accessMethod', 'retain'), 'N': ('atomic', False), 'D': ('synthesizedIvar', ''), 'P': ('gcStrength', '__strong'), 'W': ('gcStrength', '__weak'), 'G': ('hasGetter', True), 'S': ('hasSetter', True), 'R': ('readOnly', True) } # attributes defined by a letter followed by some strings. __multiLetters = {'G': 'getter', 'S': 'setter', 'V': 'synthesizedIvar'} buffer = [] for string in exploded: if buffer: buffer.append(string) else: typ = string[0] if typ in __multiLetters: setattr(self, __multiLetters[typ], string[1:]) if typ in __singleLetters: (attr, val) = __singleLetters[typ] setattr(self, attr, val) if typ == 'T': buffer = [string[1:]] if buffer: joinedBuffer = ','.join(buffer) joinedBufferLength = len(joinedBuffer) if balancedSubstring(joinedBuffer) <= joinedBufferLength: self.encoding = joinedBuffer buffer = []
def parse(encoding, start=0, end=None, hasMemberName=True): """ Parse an encoded type string into an Objective-C type. If you supply *start* and *end*, only the substring ``encoding[start:end]`` will be parsed. Returns a tuple of :class:`~objctype2.types.Type` and the next index to parse. If nothing can be parsed, the type will become ``None``. Example:: from objctype2.parser import parse from balanced_substring import numericSubstring typeinfo = 'c24@0:4@8@12{_NSRange=II}16' index = 0 while True: (type_, index) = parse(typeinfo, index) if type_ is None: break (stackIndex, index) = numericSubstring(typeinfo, index) print (type_, '@', stackIndex) # prints: # Primitive('c') @ 24 # ObjCType() @ 0 # Primitive(':') @ 4 # ObjCType() @ 8 # ObjCType() @ 12 # Struct('_NSRange').append(Primitive('I')).append(Primitive('I')).freeze() @ 16 """ if end is None: end = len(encoding) if start >= end: return (None, end) firstChar = encoding[start] start += 1 # primitives if firstChar in _primitive1c: return (Primitive(firstChar), start) # unary, or function pointer (^ and ^?) elif firstChar in _modifier1c: if start >= end or encoding[start] in "]})": return (Primitive(FUNCTION_POINTER), start) elif encoding[start] == '?': return (Primitive(FUNCTION_POINTER), start + 1) else: (baseType, newStart) = parse(encoding, start, end, hasMemberName) return (Unary(firstChar, baseType), newStart) # char pointer elif firstChar == '*': return (Unary(POINTER, Primitive(CHAR)), start) # bitfield elif firstChar == 'b': (bitlen, newStart) = numericSubstring(encoding, start) return (Bitfield(bitlen), newStart) # array elif firstChar == '[': (length, newStart) = numericSubstring(encoding, start) (baseType, newNewStart) = parse(encoding, newStart, end, hasMemberName) assert encoding[newNewStart] == ']' return (Array(length, baseType), newNewStart + 1) # objective-C type, or blocks elif firstChar == '@': if start >= end or encoding[start] not in '?"': return (ObjCType(), start) elif encoding[start] == '?': return (Primitive(BLOCK), start + 1) else: # "foo"@"bar"@ # "foo"@"NSObject""bar"@ # "foo"@"bar"@"NSObject" m = _objcRe(encoding, start) if not m or (hasMemberName and m.end() < end and encoding[m.end() - 1] not in '"]})'): return (ObjCType(), start) (name, protos) = m.groups() if protos: protos = protos.split(',') return (ObjCType(name, protos), m.end()) # struct or union elif firstChar in '{(': isUnion = firstChar == '(' newStart = start while encoding[newStart] not in '=)}': newStart = balancedSubstring(encoding, newStart) name = encoding[start:newStart] if encoding[newStart] == '=': newStart += 1 stru = Struct(name, isUnion) while newStart <= end and encoding[newStart] not in ')}': hasMemberName = encoding[newStart] == '"' if hasMemberName: m = _struMemRe(encoding, newStart) memberName = m.group(1) newStart = m.end() else: memberName = None (baseType, newNewStart) = parse(encoding, newStart, end, hasMemberName) stru.append(baseType, memberName) newStart = newNewStart stru.freeze() return (stru, newStart + 1)
def parse(encoding, start=0, end=None, hasMemberName=True): """ Parse an encoded type string into an Objective-C type. If you supply *start* and *end*, only the substring ``encoding[start:end]`` will be parsed. Returns a tuple of :class:`~objctype2.types.Type` and the next index to parse. If nothing can be parsed, the type will become ``None``. Example:: from objctype2.parser import parse from balanced_substring import numericSubstring typeinfo = 'c24@0:4@8@12{_NSRange=II}16' index = 0 while True: (type_, index) = parse(typeinfo, index) if type_ is None: break (stackIndex, index) = numericSubstring(typeinfo, index) print (type_, '@', stackIndex) # prints: # Primitive('c') @ 24 # ObjCType() @ 0 # Primitive(':') @ 4 # ObjCType() @ 8 # ObjCType() @ 12 # Struct('_NSRange').append(Primitive('I')).append(Primitive('I')).freeze() @ 16 """ if end is None: end = len(encoding) if start >= end: return (None, end) firstChar = encoding[start] start += 1 # primitives if firstChar in _primitive1c: return (Primitive(firstChar), start) # unary, or function pointer (^ and ^?) elif firstChar in _modifier1c: if start >= end or encoding[start] in "]})": return (Primitive(FUNCTION_POINTER), start) elif encoding[start] == '?': return (Primitive(FUNCTION_POINTER), start+1) else: (baseType, newStart) = parse(encoding, start, end, hasMemberName) return (Unary(firstChar, baseType), newStart) # char pointer elif firstChar == '*': return (Unary(POINTER, Primitive(CHAR)), start) # bitfield elif firstChar == 'b': (bitlen, newStart) = numericSubstring(encoding, start) return (Bitfield(bitlen), newStart) # array elif firstChar == '[': (length, newStart) = numericSubstring(encoding, start) (baseType, newNewStart) = parse(encoding, newStart, end, hasMemberName) assert encoding[newNewStart] == ']' return (Array(length, baseType), newNewStart+1) # objective-C type, or blocks elif firstChar == '@': if start >= end or encoding[start] not in '?"': return (ObjCType(), start) elif encoding[start] == '?': return (Primitive(BLOCK), start+1) else: # "foo"@"bar"@ # "foo"@"NSObject""bar"@ # "foo"@"bar"@"NSObject" m = _objcRe(encoding, start) if not m or (hasMemberName and m.end() < end and encoding[m.end()] not in '"]})'): return (ObjCType(), start) (name, protos) = m.groups() if protos: protos = protos.split(',') return (ObjCType(name, protos), m.end()) # struct or union elif firstChar in '{(': isUnion = firstChar == '(' newStart = start while encoding[newStart] not in '=)}': newStart = balancedSubstring(encoding, newStart) name = encoding[start:newStart] if encoding[newStart] == '=': newStart += 1 stru = Struct(name, isUnion) while newStart <= end and encoding[newStart] not in ')}': hasMemberName = encoding[newStart] == '"' if hasMemberName: m = _struMemRe(encoding, newStart) memberName = m.group(1) newStart = m.end() else: memberName = None (baseType, newNewStart) = parse(encoding, newStart, end, hasMemberName) stru.append(baseType, memberName) newStart = newNewStart stru.freeze() return (stru, newStart+1)