NS(Mutable)IndexSet formatter moves from Python to C++

git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@177217 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/examples/summaries/cocoa/NSIndexSet.py b/examples/summaries/cocoa/NSIndexSet.py
index a1656fe..011d58d 100644
--- a/examples/summaries/cocoa/NSIndexSet.py
+++ b/examples/summaries/cocoa/NSIndexSet.py
@@ -5,7 +5,8 @@
 This file is distributed under the University of Illinois Open Source
 License. See LICENSE.TXT for details.
 """
-# summary provider for NS(Mutable)IndexSet
+# example summary provider for NS(Mutable)IndexSet
+# the real summary is now C++ code built into LLDB
 import lldb
 import ctypes
 import lldb.runtime.objc.objc_runtime
diff --git a/include/lldb/DataFormatters/CXXFormatterFunctions.h b/include/lldb/DataFormatters/CXXFormatterFunctions.h
index 8ba709e..8c18db2 100644
--- a/include/lldb/DataFormatters/CXXFormatterFunctions.h
+++ b/include/lldb/DataFormatters/CXXFormatterFunctions.h
@@ -81,6 +81,9 @@
         NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream);
         
         bool
+        NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream);
+        
+        bool
         NSArraySummaryProvider (ValueObject& valobj, Stream& stream);
         
         template<bool cf_style>
diff --git a/source/DataFormatters/CXXFormatterFunctions.cpp b/source/DataFormatters/CXXFormatterFunctions.cpp
index 89e156d..dfd64b2 100644
--- a/source/DataFormatters/CXXFormatterFunctions.cpp
+++ b/source/DataFormatters/CXXFormatterFunctions.cpp
@@ -912,6 +912,84 @@
 }
 
 bool
+lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream)
+{
+    ProcessSP process_sp = valobj.GetProcessSP();
+    if (!process_sp)
+        return false;
+    
+    ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+    
+    if (!runtime)
+        return false;
+    
+    ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+    
+    if (!descriptor.get() || !descriptor->IsValid())
+        return false;
+    
+    uint32_t ptr_size = process_sp->GetAddressByteSize();
+    
+    lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+    
+    if (!valobj_addr)
+        return false;
+    
+    const char* class_name = descriptor->GetClassName().GetCString();
+    
+    if (!class_name || !*class_name)
+        return false;
+    
+    uint64_t count = 0;
+    
+    do {
+        if (!strcmp(class_name,"NSIndexSet") || !strcmp(class_name,"NSMutableIndexSet"))
+        {
+            Error error;
+            uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 4, 0, error);
+            if (error.Fail())
+                return false;
+            // this means the set is empty - count = 0
+            if ((mode & 1) == 1)
+            {
+                count = 0;
+                break;
+            }
+            if ((mode & 2) == 2)
+                mode = 1; // this means the set only has one range
+            else
+                mode = 2; // this means the set has multiple ranges
+            if (mode == 1)
+            {
+                count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+3*ptr_size, ptr_size, 0, error);
+                if (error.Fail())
+                    return false;
+            }
+            else
+            {
+                // read a pointer to the data at 2*ptr_size
+                count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error);
+                if (error.Fail())
+                    return false;
+                // read the data at 2*ptr_size from the first location
+                count = process_sp->ReadUnsignedIntegerFromMemory(count+2*ptr_size, ptr_size, 0, error);
+                if (error.Fail())
+                    return false;
+            }
+        }
+        else
+        {
+            if (!ExtractValueFromObjCExpression(valobj, "unsigned long long int", "count", count))
+                return false;
+        }
+    }  while (false);
+    stream.Printf("%llu index%s",
+                  count,
+                  (count == 1 ? "" : "es"));
+    return true;
+}
+
+bool
 lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream)
 {
     ProcessSP process_sp = valobj.GetProcessSP();
diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp
index afc88d4..aaf9cce 100644
--- a/source/DataFormatters/FormatManager.cpp
+++ b/source/DataFormatters/FormatManager.cpp
@@ -989,8 +989,8 @@
     AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSDate.CFAbsoluteTime_SummaryProvider", ConstString("CFAbsoluteTime"), appkit_flags);
     appkit_flags.SetDontShowValue(false);
     
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSIndexSet.NSIndexSet_SummaryProvider", ConstString("NSIndexSet"), appkit_flags);
-    AddScriptSummary(appkit_category_sp, "lldb.formatters.objc.NSIndexSet.NSIndexSet_SummaryProvider", ConstString("NSMutableIndexSet"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
+    AddCXXSummary(appkit_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSMutableIndexSet"), appkit_flags);
 
     AddStringSummary(appkit_category_sp,
                      "@\"${var.month%d}/${var.day%d}/${var.year%d} ${var.hour%d}:${var.minute%d}:${var.second}\"",