// Copyright 2013 The Servo Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Immutable strings. #[allow(non_uppercase_statics)]; use base::{Boolean, CFAllocatorRef, CFIndex, CFIndexConvertible, CFOptionFlags, CFRange}; use base::{CFRelease, CFTypeID, TCFType, kCFAllocatorDefault, kCFAllocatorNull}; use std::cast; use std::libc; use std::ptr; use std::vec; pub type UniChar = libc::c_ushort; // CFString.h pub type CFStringCompareFlags = CFOptionFlags; static kCFCompareCaseInsensitive: CFStringCompareFlags = 1; static kCFCompareBackwards: CFStringCompareFlags = 4; static kCFCompareAnchored: CFStringCompareFlags = 8; static kCFCompareNonliteral: CFStringCompareFlags = 16; static kCFCompareLocalized: CFStringCompareFlags = 32; static kCFCompareNumerically: CFStringCompareFlags = 64; static kCFCompareDiacriticInsensitive: CFStringCompareFlags = 128; static kCFCompareWidthInsensitive: CFStringCompareFlags = 256; static kCFCompareForcedOrdering: CFStringCompareFlags = 512; pub type CFStringEncoding = u32; // OS X built-in encodings. static kCFStringEncodingMacRoman: CFStringEncoding = 0; static kCFStringEncodingWindowsLatin1: CFStringEncoding = 0x0500; static kCFStringEncodingISOLatin1: CFStringEncoding = 0x0201; static kCFStringEncodingNextStepLatin: CFStringEncoding = 0x0B01; static kCFStringEncodingASCII: CFStringEncoding = 0x0600; static kCFStringEncodingUnicode: CFStringEncoding = 0x0100; static kCFStringEncodingUTF8: CFStringEncoding = 0x08000100; static kCFStringEncodingNonLossyASCII: CFStringEncoding = 0x0BFF; static kCFStringEncodingUTF16: CFStringEncoding = 0x0100; static kCFStringEncodingUTF16BE: CFStringEncoding = 0x10000100; static kCFStringEncodingUTF16LE: CFStringEncoding = 0x14000100; static kCFStringEncodingUTF32: CFStringEncoding = 0x0c000100; static kCFStringEncodingUTF32BE: CFStringEncoding = 0x18000100; static kCFStringEncodingUTF32LE: CFStringEncoding = 0x1c000100; // CFStringEncodingExt.h type CFStringEncodings = CFIndex; // External encodings, except those defined above. // Defined above: kCFStringEncodingMacRoman = 0 static kCFStringEncodingMacJapanese: CFStringEncoding = 1; static kCFStringEncodingMacChineseTrad: CFStringEncoding = 2; static kCFStringEncodingMacKorean: CFStringEncoding = 3; static kCFStringEncodingMacArabic: CFStringEncoding = 4; static kCFStringEncodingMacHebrew: CFStringEncoding = 5; static kCFStringEncodingMacGreek: CFStringEncoding = 6; static kCFStringEncodingMacCyrillic: CFStringEncoding = 7; static kCFStringEncodingMacDevanagari: CFStringEncoding = 9; static kCFStringEncodingMacGurmukhi: CFStringEncoding = 10; static kCFStringEncodingMacGujarati: CFStringEncoding = 11; static kCFStringEncodingMacOriya: CFStringEncoding = 12; static kCFStringEncodingMacBengali: CFStringEncoding = 13; static kCFStringEncodingMacTamil: CFStringEncoding = 14; static kCFStringEncodingMacTelugu: CFStringEncoding = 15; static kCFStringEncodingMacKannada: CFStringEncoding = 16; static kCFStringEncodingMacMalayalam: CFStringEncoding = 17; static kCFStringEncodingMacSinhalese: CFStringEncoding = 18; static kCFStringEncodingMacBurmese: CFStringEncoding = 19; static kCFStringEncodingMacKhmer: CFStringEncoding = 20; static kCFStringEncodingMacThai: CFStringEncoding = 21; static kCFStringEncodingMacLaotian: CFStringEncoding = 22; static kCFStringEncodingMacGeorgian: CFStringEncoding = 23; static kCFStringEncodingMacArmenian: CFStringEncoding = 24; static kCFStringEncodingMacChineseSimp: CFStringEncoding = 25; static kCFStringEncodingMacTibetan: CFStringEncoding = 26; static kCFStringEncodingMacMongolian: CFStringEncoding = 27; static kCFStringEncodingMacEthiopic: CFStringEncoding = 28; static kCFStringEncodingMacCentralEurRoman: CFStringEncoding = 29; static kCFStringEncodingMacVietnamese: CFStringEncoding = 30; static kCFStringEncodingMacExtArabic: CFStringEncoding = 31; static kCFStringEncodingMacSymbol: CFStringEncoding = 33; static kCFStringEncodingMacDingbats: CFStringEncoding = 34; static kCFStringEncodingMacTurkish: CFStringEncoding = 35; static kCFStringEncodingMacCroatian: CFStringEncoding = 36; static kCFStringEncodingMacIcelandic: CFStringEncoding = 37; static kCFStringEncodingMacRomanian: CFStringEncoding = 38; static kCFStringEncodingMacCeltic: CFStringEncoding = 39; static kCFStringEncodingMacGaelic: CFStringEncoding = 40; static kCFStringEncodingMacFarsi: CFStringEncoding = 0x8C; static kCFStringEncodingMacUkrainian: CFStringEncoding = 0x98; static kCFStringEncodingMacInuit: CFStringEncoding = 0xEC; static kCFStringEncodingMacVT100: CFStringEncoding = 0xFC; static kCFStringEncodingMacHFS: CFStringEncoding = 0xFF; // Defined above: kCFStringEncodingISOLatin1 = 0x0201 static kCFStringEncodingISOLatin2: CFStringEncoding = 0x0202; static kCFStringEncodingISOLatin3: CFStringEncoding = 0x0203; static kCFStringEncodingISOLatin4: CFStringEncoding = 0x0204; static kCFStringEncodingISOLatinCyrillic: CFStringEncoding = 0x0205; static kCFStringEncodingISOLatinArabic: CFStringEncoding = 0x0206; static kCFStringEncodingISOLatinGreek: CFStringEncoding = 0x0207; static kCFStringEncodingISOLatinHebrew: CFStringEncoding = 0x0208; static kCFStringEncodingISOLatin5: CFStringEncoding = 0x0209; static kCFStringEncodingISOLatin6: CFStringEncoding = 0x020A; static kCFStringEncodingISOLatinThai: CFStringEncoding = 0x020B; static kCFStringEncodingISOLatin7: CFStringEncoding = 0x020D; static kCFStringEncodingISOLatin8: CFStringEncoding = 0x020E; static kCFStringEncodingISOLatin9: CFStringEncoding = 0x020F; static kCFStringEncodingISOLatin10: CFStringEncoding = 0x0210; static kCFStringEncodingDOSLatinUS: CFStringEncoding = 0x0400; static kCFStringEncodingDOSGreek: CFStringEncoding = 0x0405; static kCFStringEncodingDOSBalticRim: CFStringEncoding = 0x0406; static kCFStringEncodingDOSLatin1: CFStringEncoding = 0x0410; static kCFStringEncodingDOSGreek1: CFStringEncoding = 0x0411; static kCFStringEncodingDOSLatin2: CFStringEncoding = 0x0412; static kCFStringEncodingDOSCyrillic: CFStringEncoding = 0x0413; static kCFStringEncodingDOSTurkish: CFStringEncoding = 0x0414; static kCFStringEncodingDOSPortuguese: CFStringEncoding = 0x0415; static kCFStringEncodingDOSIcelandic: CFStringEncoding = 0x0416; static kCFStringEncodingDOSHebrew: CFStringEncoding = 0x0417; static kCFStringEncodingDOSCanadianFrench: CFStringEncoding = 0x0418; static kCFStringEncodingDOSArabic: CFStringEncoding = 0x0419; static kCFStringEncodingDOSNordic: CFStringEncoding = 0x041A; static kCFStringEncodingDOSRussian: CFStringEncoding = 0x041B; static kCFStringEncodingDOSGreek2: CFStringEncoding = 0x041C; static kCFStringEncodingDOSThai: CFStringEncoding = 0x041D; static kCFStringEncodingDOSJapanese: CFStringEncoding = 0x0420; static kCFStringEncodingDOSChineseSimplif: CFStringEncoding = 0x0421; static kCFStringEncodingDOSKorean: CFStringEncoding = 0x0422; static kCFStringEncodingDOSChineseTrad: CFStringEncoding = 0x0423; // Defined above: kCFStringEncodingWindowsLatin1 = 0x0500 static kCFStringEncodingWindowsLatin2: CFStringEncoding = 0x0501; static kCFStringEncodingWindowsCyrillic: CFStringEncoding = 0x0502; static kCFStringEncodingWindowsGreek: CFStringEncoding = 0x0503; static kCFStringEncodingWindowsLatin5: CFStringEncoding = 0x0504; static kCFStringEncodingWindowsHebrew: CFStringEncoding = 0x0505; static kCFStringEncodingWindowsArabic: CFStringEncoding = 0x0506; static kCFStringEncodingWindowsBalticRim: CFStringEncoding = 0x0507; static kCFStringEncodingWindowsVietnamese: CFStringEncoding = 0x0508; static kCFStringEncodingWindowsKoreanJohab: CFStringEncoding = 0x0510; // Defined above: kCFStringEncodingASCII = 0x0600 static kCFStringEncodingANSEL: CFStringEncoding = 0x0601; static kCFStringEncodingJIS_X0201_76: CFStringEncoding = 0x0620; static kCFStringEncodingJIS_X0208_83: CFStringEncoding = 0x0621; static kCFStringEncodingJIS_X0208_90: CFStringEncoding = 0x0622; static kCFStringEncodingJIS_X0212_90: CFStringEncoding = 0x0623; static kCFStringEncodingJIS_C6226_78: CFStringEncoding = 0x0624; static kCFStringEncodingShiftJIS_X0213: CFStringEncoding = 0x0628; static kCFStringEncodingShiftJIS_X0213_MenKuTen: CFStringEncoding = 0x0629; static kCFStringEncodingGB_2312_80: CFStringEncoding = 0x0630; static kCFStringEncodingGBK_95: CFStringEncoding = 0x0631; static kCFStringEncodingGB_18030_2000: CFStringEncoding = 0x0632; static kCFStringEncodingKSC_5601_87: CFStringEncoding = 0x0640; static kCFStringEncodingKSC_5601_92_Johab: CFStringEncoding = 0x0641; static kCFStringEncodingCNS_11643_92_P1: CFStringEncoding = 0x0651; static kCFStringEncodingCNS_11643_92_P2: CFStringEncoding = 0x0652; static kCFStringEncodingCNS_11643_92_P3: CFStringEncoding = 0x0653; static kCFStringEncodingISO_2022_JP: CFStringEncoding = 0x0820; static kCFStringEncodingISO_2022_JP_2: CFStringEncoding = 0x0821; static kCFStringEncodingISO_2022_JP_1: CFStringEncoding = 0x0822; static kCFStringEncodingISO_2022_JP_3: CFStringEncoding = 0x0823; static kCFStringEncodingISO_2022_CN: CFStringEncoding = 0x0830; static kCFStringEncodingISO_2022_CN_EXT: CFStringEncoding = 0x0831; static kCFStringEncodingISO_2022_KR: CFStringEncoding = 0x0840; static kCFStringEncodingEUC_JP: CFStringEncoding = 0x0920; static kCFStringEncodingEUC_CN: CFStringEncoding = 0x0930; static kCFStringEncodingEUC_TW: CFStringEncoding = 0x0931; static kCFStringEncodingEUC_KR: CFStringEncoding = 0x0940; static kCFStringEncodingShiftJIS: CFStringEncoding = 0x0A01; static kCFStringEncodingKOI8_R: CFStringEncoding = 0x0A02; static kCFStringEncodingBig5: CFStringEncoding = 0x0A03; static kCFStringEncodingMacRomanLatin1: CFStringEncoding = 0x0A04; static kCFStringEncodingHZ_GB_2312: CFStringEncoding = 0x0A05; static kCFStringEncodingBig5_HKSCS_1999: CFStringEncoding = 0x0A06; static kCFStringEncodingVISCII: CFStringEncoding = 0x0A07; static kCFStringEncodingKOI8_U: CFStringEncoding = 0x0A08; static kCFStringEncodingBig5_E: CFStringEncoding = 0x0A09; // Defined above: kCFStringEncodingNextStepLatin = 0x0B01 static kCFStringEncodingNextStepJapanese: CFStringEncoding = 0x0B02; static kCFStringEncodingEBCDIC_US: CFStringEncoding = 0x0C01; static kCFStringEncodingEBCDIC_CP037: CFStringEncoding = 0x0C02; static kCFStringEncodingUTF7: CFStringEncoding = 0x04000100; static kCFStringEncodingUTF7_IMAP: CFStringEncoding = 0x0A10; static kCFStringEncodingShiftJIS_X0213_00: CFStringEncoding = 0x0628; /* Deprecated */ struct __CFString; pub type CFStringRef = *__CFString; /// An immutable string in one of a variety of encodings. /// /// FIXME(pcwalton): Should be a newtype struct, but that fails due to a Rust compiler bug. pub struct CFString { priv obj: CFStringRef, } impl Clone for CFString { #[fixed_stack_segment] #[inline] fn clone(&self) -> CFString { unsafe { TCFType::wrap_under_get_rule(self.obj) } } } impl Drop for CFString { #[fixed_stack_segment] fn drop(&mut self) { unsafe { CFRelease(self.as_CFTypeRef()) } } } impl TCFType for CFString { fn as_concrete_TypeRef(&self) -> CFStringRef { self.obj } unsafe fn wrap_under_create_rule(obj: CFStringRef) -> CFString { CFString { obj: obj, } } #[fixed_stack_segment] #[inline] fn type_id(_: Option) -> CFTypeID { unsafe { CFStringGetTypeID() } } } impl FromStr for CFString { /// Creates a new `CFString` instance from a Rust string. #[fixed_stack_segment] #[inline] fn from_str(string: &str) -> Option { unsafe { let string_ref = string.as_imm_buf(|bytes, len| { CFStringCreateWithBytes(kCFAllocatorDefault, bytes, len.to_CFIndex(), kCFStringEncodingUTF8, false as Boolean, kCFAllocatorNull) }); Some(TCFType::wrap_under_create_rule(string_ref)) } } } impl ToStr for CFString { #[fixed_stack_segment] fn to_str(&self) -> ~str { unsafe { let char_len = self.char_len(); let range = CFRange::init(0, char_len); // First, ask how big the buffer ought to be. let mut bytes_required: CFIndex = 0; CFStringGetBytes(self.obj, range, kCFStringEncodingUTF8, 0, false as Boolean, ptr::null(), 0, &mut bytes_required); // Then, allocate the buffer and actually copy. let buffer: ~[u8] = vec::from_elem(bytes_required as uint, '\x00' as u8); let mut bytes_used: CFIndex = 0; let chars_written = CFStringGetBytes(self.obj, range, kCFStringEncodingUTF8, 0, false as Boolean, vec::raw::to_ptr(buffer), buffer.len().to_CFIndex(), &mut bytes_used) as uint; assert!(chars_written.to_CFIndex() == char_len); // This is dangerous; we over-allocate and null-terminate the string (during // initialization). assert!(bytes_used == buffer.len().to_CFIndex()); // Then, reinterpret it as as string. You have been warned! cast::transmute(buffer) } } } impl CFString { /// Like `CFString::from_string`, but references a string that can be used as a backing store /// by virtue of being statically allocated. #[fixed_stack_segment] #[inline] pub fn from_static_string(string: &'static str) -> CFString { unsafe { let string_ref = string.as_imm_buf(|bytes, len| { CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, len.to_CFIndex(), kCFStringEncodingUTF8, false as Boolean, kCFAllocatorNull) }); TCFType::wrap_under_create_rule(string_ref) } } /// Returns the number of characters in the string. #[fixed_stack_segment] #[inline] pub fn char_len(&self) -> CFIndex { unsafe { CFStringGetLength(self.obj) } } } #[link_args="-framework CoreFoundation"] #[nolink] extern { /* * CFString.h */ // N.B. organized according to "Functions by task" in docs /* Creating a CFString */ //fn CFSTR //fn CFStringCreateArrayBySeparatingStrings //fn CFStringCreateByCombiningStrings //fn CFStringCreateCopy //fn CFStringCreateFromExternalRepresentation fn CFStringCreateWithBytes(alloc: CFAllocatorRef, bytes: *u8, numBytes: CFIndex, encoding: CFStringEncoding, isExternalRepresentation: Boolean, contentsDeallocator: CFAllocatorRef) -> CFStringRef; fn CFStringCreateWithBytesNoCopy(alloc: CFAllocatorRef, bytes: *u8, numBytes: CFIndex, encoding: CFStringEncoding, isExternalRepresentation: Boolean, contentsDeallocator: CFAllocatorRef) -> CFStringRef; //fn CFStringCreateWithCharacters //fn CFStringCreateWithCharactersNoCopy //fn CFStringCreateWithCString //fn CFStringCreateWithCStringNoCopy //fn CFStringCreateWithFormat //fn CFStringCreateWithFormatAndArguments //fn CFStringCreateWithPascalString //fn CFStringCreateWithPascalStringNoCopy //fn CFStringCreateWithSubstring /* Searching Strings */ //fn CFStringCreateArrayWithFindResults //fn CFStringFind //fn CFStringFindCharacterFromSet //fn CFStringFindWithOptions //fn CFStringFindWithOptionsAndLocale //fn CFStringGetLineBounds /* Comparing Strings */ //fn CFStringCompare //fn CFStringCompareWithOptions //fn CFStringCompareWithOptionsAndLocale //fn CFStringHasPrefix //fn CFStringHasSuffix /* Accessing Characters */ //fn CFStringCreateExternalRepresentation fn CFStringGetBytes(theString: CFStringRef, range: CFRange, encoding: CFStringEncoding, lossByte: u8, isExternalRepresentation: Boolean, buffer: *u8, maxBufLen: CFIndex, usedBufLen: *mut CFIndex) -> CFIndex; //fn CFStringGetCharacterAtIndex //fn CFStringGetCharacters //fn CFStringGetCharactersPtr //fn CFStringGetCharacterFromInlineBuffer //fn CFStringGetCString //fn CFStringGetCStringPtr fn CFStringGetLength(theString: CFStringRef) -> CFIndex; //fn CFStringGetPascalString //fn CFStringGetPascalStringPtr //fn CFStringGetRangeOfComposedCharactersAtIndex //fn CFStringInitInlineBuffer /* Working With Hyphenation */ //fn CFStringGetHyphenationLocationBeforeIndex //fn CFStringIsHyphenationAvailableForLocale /* Working With Encodings */ //fn CFStringConvertEncodingToIANACharSetName //fn CFStringConvertEncodingToNSStringEncoding //fn CFStringConvertEncodingToWindowsCodepage //fn CFStringConvertIANACharSetNameToEncoding //fn CFStringConvertNSStringEncodingToEncoding //fn CFStringConvertWindowsCodepageToEncoding //fn CFStringGetFastestEncoding //fn CFStringGetListOfAvailableEncodings //fn CFStringGetMaximumSizeForEncoding //fn CFStringGetMostCompatibleMacStringEncoding //fn CFStringGetNameOfEncoding //fn CFStringGetSmallestEncoding //fn CFStringGetSystemEncoding //fn CFStringIsEncodingAvailable /* Getting Numeric Values */ //fn CFStringGetDoubleValue //fn CFStringGetIntValue /* Getting String Properties */ //fn CFShowStr fn CFStringGetTypeID() -> CFTypeID; /* String File System Representations */ //fn CFStringCreateWithFileSystemRepresentation //fn CFStringGetFileSystemRepresentation //fn CFStringGetMaximumSizeOfFileSystemRepresentation /* Getting Paragraph Bounds */ //fn CFStringGetParagraphBounds /* Managing Surrogates */ //fn CFStringGetLongCharacterForSurrogatePair //fn CFStringGetSurrogatePairForLongCharacter //fn CFStringIsSurrogateHighCharacter //fn CFStringIsSurrogateLowCharacter } #[test] fn string_and_back() { let original = "The quick brown fox jumped over the slow lazy dog."; let cfstr = CFString::from_static_string(original); let converted = cfstr.to_str(); assert!(original == converted); }