Files
core-foundation-rs/string.rs
T
Jack Moffitt 7ddceb0c98 Upgrade to latest Rust.
We can no longer transmute from type params, so we must expand the
default methods that do this into all the places that implement the
trait. Yuck.
2014-06-27 12:28:15 -06:00

470 lines
20 KiB
Rust

// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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, CFRetain, CFTypeID, CFTypeRef, TCFType};
use base::{kCFAllocatorDefault, kCFAllocatorNull};
use libc;
use std::fmt;
use std::from_str::FromStr;
use std::mem;
use std::ptr;
use std::vec::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 {
obj: CFStringRef,
}
impl Clone for CFString {
#[inline]
fn clone(&self) -> CFString {
unsafe {
TCFType::wrap_under_get_rule(self.obj)
}
}
}
impl Drop for CFString {
fn drop(&mut self) {
unsafe {
CFRelease(self.as_CFTypeRef())
}
}
}
impl TCFType<CFStringRef> for CFString {
#[inline]
fn as_concrete_TypeRef(&self) -> CFStringRef {
self.obj
}
#[inline]
unsafe fn wrap_under_get_rule(reference: CFStringRef) -> CFString {
let reference: CFStringRef = mem::transmute(CFRetain(mem::transmute(reference)));
TCFType::wrap_under_create_rule(reference)
}
#[inline]
fn as_CFTypeRef(&self) -> CFTypeRef {
unsafe {
mem::transmute(self.as_concrete_TypeRef())
}
}
unsafe fn wrap_under_create_rule(obj: CFStringRef) -> CFString {
CFString {
obj: obj,
}
}
#[inline]
fn type_id(_: Option<CFString>) -> CFTypeID {
unsafe {
CFStringGetTypeID()
}
}
}
impl FromStr for CFString {
/// Creates a new `CFString` instance from a Rust string.
#[inline]
fn from_str(string: &str) -> Option<CFString> {
unsafe {
let string_ref = CFStringCreateWithBytes(kCFAllocatorDefault,
string.as_ptr(),
string.len().to_CFIndex(),
kCFStringEncodingUTF8,
false as Boolean,
kCFAllocatorNull);
Some(TCFType::wrap_under_create_rule(string_ref))
}
}
}
impl fmt::Show for CFString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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: Vec<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,
buffer.as_ptr(),
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());
String::from_utf8(buffer).unwrap().fmt(f)
}
}
}
impl CFString {
/// Like `CFString::from_string`, but references a string that can be used as a backing store
/// by virtue of being statically allocated.
#[inline]
pub fn from_static_string(string: &'static str) -> CFString {
unsafe {
let string_ref = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
string.as_ptr(),
string.len().to_CFIndex(),
kCFStringEncodingUTF8,
false as Boolean,
kCFAllocatorNull);
TCFType::wrap_under_create_rule(string_ref)
}
}
/// Returns the number of characters in the string.
#[inline]
pub fn char_len(&self) -> CFIndex {
unsafe {
CFStringGetLength(self.obj)
}
}
}
#[link(name = "CoreFoundation", kind = "framework")]
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.as_slice());
}