Last active
August 29, 2015 13:56
-
-
Save pzol/9039214 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[allow(ctypes, dead_code)]; | |
| #[feature(globs)]; | |
| use std::str; | |
| use std::libc::{ c_char }; | |
| pub type UChar = u16; | |
| pub type UChar32 = i32; | |
| #[deriving(Eq)] | |
| pub enum UErrorCode { | |
| ZERO_ERROR = 0, | |
| BUFFER_OVERFLOW_ERROR = 15 | |
| } | |
| pub struct UBreakIterator; | |
| pub enum UBreakIteratorType { | |
| UBRK_CHARACTER, | |
| UBRK_WORD, | |
| UBRK_LINE, | |
| UBRK_SENTENCE, | |
| UBRK_TITLE | |
| } | |
| pub static TRUE: u8 = 1u8; | |
| pub static FALSE: u8 = 0u8; | |
| pub static SENTINEL: UChar32 = -1; | |
| mod icuio { | |
| use super::*; | |
| #[link(name = "icuio")] | |
| extern "C" { | |
| pub fn u_printf_u_52(patternSpecification: *UChar, ...) -> i32; | |
| } | |
| } | |
| mod icui18n { | |
| use super::*; | |
| struct URegularExpression; | |
| #[link(name = "icui18n")] | |
| extern "C" { | |
| pub fn uregex_split_52(regexp: *URegularExpression, destBuf: *mut UChar, destCapacity: i32, requiredCapacity: *i32, destFields: &[*UChar], destFieldsCapacity: i32, status: *mut UErrorCode) -> i32; | |
| } | |
| } | |
| mod icuuc { | |
| use super::*; | |
| use std::libc::{ c_char }; | |
| #[link(name = "icuuc")] | |
| extern "C" { | |
| // http://icu-project.org/apiref/icu4c/ustring_8h.html | |
| pub fn u_strToUpper_52(dest: *mut UChar, destCapacity: i32, src: *UChar, srcLength: i32, locale: *c_char, pErrorCode: *mut UErrorCode) -> i32; | |
| pub fn u_strToLower_52(dest: *mut UChar, destCapacity: i32, src: *UChar, srcLength: i32, locale: *c_char, pErrorCode: *mut UErrorCode) -> i32; | |
| pub fn u_strlen_52(s: *UChar) -> i32; | |
| pub fn u_errorName_52(code: i32) -> *char; | |
| pub fn u_strFromUTF8WithSub_52(dest: *mut UChar, destCapacity: i32, pDestLength: *mut i32, src: *c_char, srcLength: i32, subChar: UChar32, pNumSubstitutions: *mut i32, pErrorCode: *mut UErrorCode) -> *mut UChar; | |
| pub fn u_strToUTF8WithSub_52(dest: *mut c_char, destCapacity: i32, pDestLength: *mut i32, src: *UChar, srcLength: i32, subChar: UChar32, pNumSubstitutions: *mut i32, pErrorCode: *mut UErrorCode) -> *mut UChar; | |
| pub fn u_strToTitle_52(dest: *mut UChar, destCapacity: i32, src: *UChar, srcLength: i32, titleIter: *UBreakIterator, locale: *c_char, pErrorCode: *mut UErrorCode) -> i32; | |
| pub fn u_strcat_52(dest: *mut UChar, src: *UChar) -> *mut UChar; | |
| pub fn u_strtok_r_52(src: *mut UChar, delim: *UChar, saveState: *mut *mut UChar) -> *UChar; | |
| pub fn u_tolower_52(c: UChar32) -> UChar32; | |
| pub fn u_toupper_52(c: UChar32) -> UChar32; | |
| } | |
| } | |
| #[inline] | |
| pub fn to_upper(c: UChar32) -> UChar32 { | |
| unsafe { icuuc::u_toupper_52(c) } | |
| } | |
| #[inline] | |
| pub fn to_lower(c: UChar32) -> UChar32 { | |
| unsafe { icuuc::u_tolower_52(c) } | |
| } | |
| // Adapters to the ICUUC versions, in case their signature changes. Also to hide the u_.*_52 and unsafe calls | |
| #[inline] | |
| pub fn strtok_r(src: *mut UChar, delim: *UChar, saveState: *mut *mut UChar) -> *UChar { | |
| unsafe { | |
| icuuc::u_strtok_r_52(src, delim, saveState) | |
| } | |
| } | |
| #[inline] | |
| pub fn strFromUTF8WithSub(dest: *mut UChar, destCapacity: i32, pDestLength: *mut i32, src: *c_char, srcLength: i32, subChar: UChar32, pNumSubstitutions: *mut i32, pErrorCode: *mut UErrorCode) -> *mut UChar { | |
| unsafe { | |
| icuuc::u_strFromUTF8WithSub_52(dest, destCapacity, pDestLength, src, srcLength, subChar, pNumSubstitutions, pErrorCode) | |
| } | |
| } | |
| #[inline] | |
| pub fn strToUTF8WithSub(dest: *mut c_char, destCapacity: i32, pDestLength: *mut i32, src: *UChar, srcLength: i32, subChar: UChar32, pNumSubstitutions: *mut i32, pErrorCode: *mut UErrorCode) -> *mut UChar { | |
| unsafe { | |
| icuuc::u_strToUTF8WithSub_52(dest, destCapacity, pDestLength, src, srcLength, subChar, pNumSubstitutions, pErrorCode) | |
| } | |
| } | |
| #[inline] | |
| pub fn strToLower(dest: *mut UChar, destCapacity: i32, src: *UChar, srcLength: i32, locale: *c_char, pErrorCode: *mut UErrorCode) -> i32 { | |
| unsafe { | |
| icuuc::u_strToLower_52(dest, destCapacity, src, srcLength, locale, pErrorCode) | |
| } | |
| } | |
| #[inline] | |
| pub fn strToUpper(dest: *mut UChar, destCapacity: i32, src: *UChar, srcLength: i32, locale: *c_char, pErrorCode: *mut UErrorCode) -> i32 { | |
| unsafe { | |
| icuuc::u_strToUpper_52(dest, destCapacity, src, srcLength, locale, pErrorCode) | |
| } | |
| } | |
| #[inline] | |
| pub fn strcat(dest: *mut UChar, src: *UChar) -> *mut UChar { | |
| unsafe { | |
| icuuc::u_strcat_52(dest, src) | |
| } | |
| } | |
| #[inline] | |
| pub fn strToTitle(dest: *mut UChar, destCapacity: i32, src: *UChar, srcLength: i32, titleIter: *UBreakIterator, locale: *c_char, pErrorCode: *mut UErrorCode) -> i32 { | |
| unsafe { | |
| icuuc::u_strToTitle_52(dest, destCapacity, src, srcLength, titleIter, locale, pErrorCode) | |
| } | |
| } | |
| #[inline] | |
| pub fn strlen(buf: *UChar) -> i32 { | |
| unsafe { | |
| icuuc::u_strlen_52(buf) | |
| } | |
| } | |
| #[inline] | |
| pub fn error_name(code: UErrorCode) -> ~str { | |
| unsafe { | |
| str::raw::from_c_str(icuuc::u_errorName_52(code as i32) as *i8) | |
| } | |
| } | |
| #[inline] | |
| pub fn success(code: UErrorCode) -> bool { | |
| code == ZERO_ERROR | |
| } | |
| #[inline] | |
| pub fn failure(code: UErrorCode) -> bool { | |
| code != ZERO_ERROR | |
| } | |
| #[inline] | |
| pub fn printf(buf: *UChar) { | |
| unsafe { | |
| icuio::u_printf_u_52(buf); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #[crate_id = "ustr#0.1"]; | |
| #[crate_type = "lib"]; | |
| #[license = "MIT"]; | |
| #[feature(globs)]; | |
| #[allow(dead_code)]; | |
| extern crate extra; | |
| pub use ffi::*; | |
| use std::{ fmt, ptr, vec, str }; | |
| mod ffi; | |
| #[deriving(Eq, Clone)] | |
| pub struct UString { | |
| buf: ~[UChar] // UChar *ptr; | |
| } | |
| //////////////////////////////////// Traits //////////////////////////////////// | |
| pub trait ToUString { | |
| fn to_u(&self) -> UString; | |
| } | |
| pub trait UJoin { | |
| fn join(&self, delim: &UString) -> UString; | |
| } | |
| impl UJoin for ~[UString] { | |
| fn join(&self, delim: &UString) -> UString { | |
| let mut it = self.iter(); | |
| match it.next() { | |
| None => UString::new(), | |
| Some(u) => { | |
| let mut result = u.to_owned(); | |
| for word in it { | |
| result = result.concat(delim).concat(word); | |
| } | |
| result | |
| } | |
| } | |
| } | |
| } | |
| impl<'a> ToUString for &'a str { | |
| fn to_u(&self) -> UString { | |
| if self.len() == 0 { | |
| return UString::new(); | |
| } | |
| let cap = self.len() * 2; | |
| let mut buf: ~[UChar] = vec::from_elem(cap, 0u16); | |
| let mut pDestLength = 0; | |
| let mut pNumSubstitutions: i32 = 0; | |
| let mut error_code = ZERO_ERROR; | |
| ffi::strFromUTF8WithSub(buf.as_mut_ptr(), | |
| buf.capacity() as i32, | |
| &mut pDestLength, | |
| self.as_bytes().as_ptr() as *i8, | |
| self.len() as i32, | |
| SENTINEL, | |
| &mut pNumSubstitutions, | |
| &mut error_code); | |
| assert!(success(error_code), ffi::error_name(error_code)); | |
| unsafe { buf.set_len(pDestLength as uint); } | |
| UString { buf: buf } | |
| } | |
| } | |
| impl fmt::Show for UString { | |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
| write!(f.buf, "{}", self.to_str()) | |
| } | |
| } | |
| impl Add<UString, UString> for UString { | |
| fn add(&self, other: &UString) -> UString { | |
| self.concat(other) | |
| } | |
| } | |
| impl ToStr for UString { | |
| fn to_str(&self) -> ~str { | |
| let mut buf: ~[u8] = vec::from_elem(self.strlen() * 2, 0u8); | |
| let mut pDestLength = 0; | |
| let mut pNumSubstitutions: i32 = 0; | |
| let mut error_code = ZERO_ERROR; | |
| ffi::strToUTF8WithSub(buf.as_mut_ptr() as *mut i8, | |
| buf.capacity() as i32, | |
| &mut pDestLength, | |
| self.buf.as_ptr(), | |
| self.buf.len() as i32, // length, requires 0 termination of src | |
| SENTINEL, | |
| &mut pNumSubstitutions, | |
| &mut error_code); | |
| unsafe { buf.set_len(pDestLength as uint); } | |
| str::from_utf8_owned(buf).unwrap_or(~"") | |
| } | |
| } | |
| impl UString { | |
| pub fn new() -> UString { | |
| UString { buf: ~[]} | |
| } | |
| #[inline] | |
| pub fn from_bytes(src: *UChar) -> UString { | |
| let len = ffi::strlen(src); | |
| let buf = unsafe { vec::raw::from_buf_raw(src, len as uint) }; | |
| UString { buf: buf } | |
| } | |
| pub fn as_ptr(&self) -> *UChar { | |
| self.buf.as_ptr() | |
| } | |
| //////////////////////////////////// PUBLIC API //////////////////////////////////// | |
| pub fn inspect(&self) -> ~str { | |
| format!("UString \\{\"{:s}\", buf: {:?}\\}", self.to_str(), self.buf) | |
| } | |
| pub fn to_owned(&self) -> UString { | |
| UString { buf: self.buf.to_owned() } | |
| } | |
| pub fn concat(&self, other: &UString) -> UString { | |
| UString { buf: self.buf + other.buf } | |
| } | |
| pub fn concat_str(&self, other: &str) -> UString { | |
| self.concat(&other.to_u()) | |
| } | |
| pub fn chars<'a>(&'a self) -> vec::Items<'a, UChar> { | |
| self.buf.iter() | |
| } | |
| // Returns a new copy of UString with all uppercase letters replaced with their uppercase counterparts. | |
| pub fn upcase(&self) -> UString { | |
| let buf = self.buf.map(|c| ffi::to_upper(*c as UChar32) as UChar); | |
| UString { buf: buf } | |
| } | |
| // Returns a new copy of UString with all lowercase letters replaced with their uppercase counterparts. | |
| pub fn downcase(&self) -> UString { | |
| let buf = self.buf.map(|c| ffi::to_lower(*c as UChar32) as UChar); | |
| UString { buf: buf } | |
| } | |
| pub fn titleize(&self) -> UString { | |
| let mut buf: ~[UChar] = vec::from_elem(self.buf.len() + 1, 0u16); | |
| let dummy = 0; | |
| let mut error_code = ZERO_ERROR; | |
| ffi::strToTitle(buf.as_mut_ptr(), | |
| buf.capacity() as i32, | |
| self.buf.as_ptr(), | |
| self.buf.len() as i32, | |
| ptr::null(), // break iterator | |
| UString::null_locale(), // locale | |
| &mut error_code); | |
| assert!(success(error_code), ffi::error_name(error_code)); | |
| unsafe { buf.set_len(self.buf.len()) }; | |
| UString { buf: buf } | |
| } | |
| pub fn split(&self, delim: UString) -> ~[UString] { | |
| let mut words = ~[]; | |
| let mut word = ~[]; | |
| for c in self.buf.iter() { | |
| if delim.buf.contains(c) { | |
| if word.len() > 0 { | |
| words.push(UString { buf: word.clone() }); | |
| word = ~[]; | |
| } | |
| } else { | |
| word.push(*c); | |
| } | |
| } | |
| if word.len() > 0 { | |
| words.push(UString { buf: word }); | |
| } | |
| words | |
| } | |
| pub fn starts_with(&self, prefix: &UString) -> bool { | |
| self.buf.starts_with(prefix.buf) | |
| } | |
| pub fn ends_with(&self, postfix: &UString) -> bool { | |
| self.buf.ends_with(postfix.buf) | |
| } | |
| pub fn slice(&self, start: uint, length: uint) -> UString { | |
| let it = self.buf.iter().skip(start).take(length); | |
| let buf = it.map(|e| e.clone()).to_owned_vec(); | |
| UString { buf: buf } | |
| } | |
| fn slice_pos(pos: int, len: uint) -> uint { | |
| let ilen = len as int; | |
| let result = match pos { | |
| p if p < 0 && ilen + p < 0 => 0, | |
| p if p < 0 => ilen + p, | |
| p => p | |
| } as uint; | |
| result | |
| } | |
| pub fn slice_r(&self, start: int, the_end: int) -> UString { | |
| let rstart = slice_pos(start, self.len()); | |
| let rend = slice_pos(the_end, self.len()); | |
| let mut pos = rstart; | |
| let it = self.buf.iter().skip(rstart).take_while(|_| { pos = pos + 1; pos -1 <= rend } ); | |
| let buf = it.map(|e| e.clone()).to_owned_vec(); | |
| UString { buf: buf } | |
| } | |
| pub fn len(&self) -> uint { | |
| self.buf.len() | |
| } | |
| fn null_locale() -> *i8 { | |
| "".as_bytes().as_ptr() as *i8 | |
| } | |
| fn strlen(&self) -> uint { | |
| ffi::strlen(self.as_ptr()) as uint | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment