| // Copyright 2016 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "base/mac/objc_release_properties.h" | 
 |  | 
 | #include <memory> | 
 |  | 
 | #include <objc/runtime.h> | 
 |  | 
 | #include "base/logging.h" | 
 | #include "base/memory/free_deleter.h" | 
 |  | 
 | namespace { | 
 |  | 
 | bool IsRetained(objc_property_t property) { | 
 |   // The format of the string returned by property_getAttributes is documented | 
 |   // at | 
 |   // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtPropertyIntrospection.html#//apple_ref/doc/uid/TP40008048-CH101-SW6 | 
 |   const char* attribute = property_getAttributes(property); | 
 |   while (attribute[0]) { | 
 |     switch (attribute[0]) { | 
 |       case 'C':  // copy | 
 |       case '&':  // retain | 
 |         return true; | 
 |     } | 
 |     do { | 
 |       attribute++; | 
 |     } while (attribute[0] && attribute[-1] != ','); | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | id ValueOf(id obj, objc_property_t property) { | 
 |   std::unique_ptr<char, base::FreeDeleter> ivar_name( | 
 |       property_copyAttributeValue(property, "V"));  // instance variable name | 
 |   if (!ivar_name) | 
 |     return nil; | 
 |   id ivar_value = nil; | 
 |   Ivar ivar = object_getInstanceVariable(obj, &*ivar_name, | 
 |                                          reinterpret_cast<void**>(&ivar_value)); | 
 |   DCHECK(ivar); | 
 |   return ivar_value; | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | namespace base { | 
 | namespace mac { | 
 | namespace details { | 
 |  | 
 | void ReleaseProperties(id self, Class cls) { | 
 |   unsigned int property_count; | 
 |   std::unique_ptr<objc_property_t[], base::FreeDeleter> properties( | 
 |       class_copyPropertyList(cls, &property_count)); | 
 |   for (size_t i = 0; i < property_count; ++i) { | 
 |     objc_property_t property = properties[i]; | 
 |     if (!IsRetained(property)) | 
 |       continue; | 
 |     [ValueOf(self, property) release]; | 
 |   } | 
 | } | 
 |  | 
 | }  // namespace details | 
 | }  // namespace mac | 
 | }  // namespace base |