"""
LLDB AppKit formatters

part of The LLVM Compiler Infrastructure
This file is distributed under the University of Illinois Open Source
License. See LICENSE.TXT for details.
"""
# example summary provider for NSArray
# the real summary is now C++ code built into LLDB
import lldb
import ctypes
import lldb.runtime.objc.objc_runtime
import lldb.formatters.metrics
import lldb.formatters.Logger

statistics = lldb.formatters.metrics.Metrics()
statistics.add_metric('invalid_isa')
statistics.add_metric('invalid_pointer')
statistics.add_metric('unknown_class')
statistics.add_metric('code_notrun')

# much less functional than the other two cases below
# just runs code to get to the count and then returns
# no children
class NSArrayKVC_SynthProvider:

	def adjust_for_architecture(self):
		pass

	def __init__(self, valobj, dict, params):
		logger = lldb.formatters.Logger.Logger()
		self.valobj = valobj;
		self.update()

	def update(self):
		logger = lldb.formatters.Logger.Logger()
		self.adjust_for_architecture();

	def num_children(self):
		logger = lldb.formatters.Logger.Logger()
		stream = lldb.SBStream()
		self.valobj.GetExpressionPath(stream)
		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
		if num_children_vo.IsValid():
			return num_children_vo.GetValueAsUnsigned(0)
		return "<variable is not NSArray>"

# much less functional than the other two cases below
# just runs code to get to the count and then returns
# no children
class NSArrayCF_SynthProvider:

	def adjust_for_architecture(self):
		pass

	def __init__(self, valobj, dict, params):
		logger = lldb.formatters.Logger.Logger()
		self.valobj = valobj;
		self.sys_params = params
		if not (self.sys_params.types_cache.ulong):
			self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
		self.update()

	def update(self):
		logger = lldb.formatters.Logger.Logger()
		self.adjust_for_architecture();

	def num_children(self):
		logger = lldb.formatters.Logger.Logger()
		num_children_vo = self.valobj.CreateChildAtOffset("count",
							self.sys_params.cfruntime_size,
							self.sys_params.types_cache.ulong)
		return num_children_vo.GetValueAsUnsigned(0)

class NSArrayI_SynthProvider:
	def adjust_for_architecture(self):
		pass

	def __init__(self, valobj, dict, params):
		logger = lldb.formatters.Logger.Logger()
		self.valobj = valobj;
		self.sys_params = params
		if not(self.sys_params.types_cache.long):
			self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
		self.update()

	def update(self):
		logger = lldb.formatters.Logger.Logger()
		self.adjust_for_architecture();

	# skip the isa pointer and get at the size
	def num_children(self):
		logger = lldb.formatters.Logger.Logger()
		count = self.valobj.CreateChildAtOffset("count",
				self.sys_params.pointer_size,
				self.sys_params.types_cache.long);
		return count.GetValueAsUnsigned(0)

class NSArrayM_SynthProvider:
	def adjust_for_architecture(self):
		pass

	def __init__(self, valobj, dict, params):
		logger = lldb.formatters.Logger.Logger()
		self.valobj = valobj;
		self.sys_params = params
		if not(self.sys_params.types_cache.long):
			self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
		self.update()

	def update(self):
		logger = lldb.formatters.Logger.Logger()
		self.adjust_for_architecture();

	# skip the isa pointer and get at the size
	def num_children(self):
		logger = lldb.formatters.Logger.Logger()
		count = self.valobj.CreateChildAtOffset("count",
				self.sys_params.pointer_size,
				self.sys_params.types_cache.long);
		return count.GetValueAsUnsigned(0)

# this is the actual synth provider, but is just a wrapper that checks
# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
# appropriate backend layer to do the computations 
class NSArray_SynthProvider:
	def adjust_for_architecture(self):
		pass

	def __init__(self, valobj, dict):
		logger = lldb.formatters.Logger.Logger()
		self.valobj = valobj;
		self.adjust_for_architecture()
		self.error = False
		self.wrapper = self.make_wrapper()
		self.invalid = (self.wrapper == None)

	def num_children(self):
		logger = lldb.formatters.Logger.Logger()
		if self.wrapper == None:
			return 0;
		return self.wrapper.num_children()

	def update(self):
		logger = lldb.formatters.Logger.Logger()
		if self.wrapper == None:
			return
		self.wrapper.update()

	# this code acts as our defense against NULL and unitialized
	# NSArray pointers, which makes it much longer than it would be otherwise
	def make_wrapper(self):
		logger = lldb.formatters.Logger.Logger()
		if self.valobj.GetValueAsUnsigned() == 0:
			self.error = True
			return lldb.runtime.objc.objc_runtime.InvalidPointer_Description(True)
		else:
			global statistics
			class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(self.valobj,statistics)
			if wrapper:
				self.error = True
				return wrapper
		
		name_string = class_data.class_name()
		
		logger >> "Class name is " + str(name_string)
		
		if name_string == '__NSArrayI':
			wrapper = NSArrayI_SynthProvider(self.valobj, dict, class_data.sys_params)
			statistics.metric_hit('code_notrun',self.valobj.GetName())
		elif name_string == '__NSArrayM':
			wrapper = NSArrayM_SynthProvider(self.valobj, dict, class_data.sys_params)
			statistics.metric_hit('code_notrun',self.valobj.GetName())
		elif name_string == '__NSCFArray':
			wrapper = NSArrayCF_SynthProvider(self.valobj, dict, class_data.sys_params)
			statistics.metric_hit('code_notrun',self.valobj.GetName())
		else:
			wrapper = NSArrayKVC_SynthProvider(self.valobj, dict, class_data.sys_params)
			statistics.metric_hit('unknown_class',str(self.valobj.GetName()) + " seen as " + name_string)
		return wrapper;

def CFArray_SummaryProvider (valobj,dict):
	logger = lldb.formatters.Logger.Logger()
	provider = NSArray_SynthProvider(valobj,dict);
	if provider.invalid == False:
		if provider.error == True:
			return provider.wrapper.message()
		try:
			summary = int(provider.num_children());
		except:
			summary = None
		logger >> "provider gave me " + str(summary)
		if summary == None:
			summary = '<variable is not NSArray>'
		elif isinstance(summary,basestring):
			pass
		else:
			# we format it like it were a CFString to make it look the same as the summary from Xcode
			summary = '@"' + str(summary) + (" objects" if summary != 1 else " object") + '"'
		return summary
	return 'Summary Unavailable'

def __lldb_init_module(debugger,dict):
	debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")
