Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  parse.rs

  Sprache: Rust
 

use super::{Timespec, Tm, at_utc, ParseError, NSEC_PER_SEC};

/// Parses the time from the string according to the format string.
pub fn strptime(mut s: &str, format: &str) -> Result<Tm, ParseError> {
    let mut tm = Tm {
        tm_sec: 0,
        tm_min: 0,
        tm_hour: 0,
        tm_mday: 0,
        tm_mon: 0,
        tm_year: 0,
        tm_wday: 0,
        tm_yday: 0,
        tm_isdst: 0,
        tm_utcoff: 0,
        tm_nsec: 0,
    };
    let mut chars = format.chars();

    while let Some(ch) = chars.next() {
        if ch == '%' {
            if let Some(ch) = chars.next() {
                parse_type(&mut s, ch, &mut tm)?;
            }
        } else {
            parse_char(&mut s, ch)?;
        }
    }

    Ok(tm)
}

fn parse_type(s: &mut &str, ch: char, tm: &mut Tm) -> Result<(), ParseError> {
    match ch {
        'A' => match match_strs(s, &[("Sunday"0),
                                     ("Monday"1),
                                     ("Tuesday"2),
                                     ("Wednesday"3),
                                     ("Thursday"4),
                                     ("Friday"5),
                                     ("Saturday"6)]) {
            Some(v) => { tm.tm_wday = v; Ok(()) }
            None => Err(ParseError::InvalidDay)
        },
        'a' => match match_strs(s, &[("Sun"0),
                                     ("Mon"1),
                                     ("Tue"2),
                                     ("Wed"3),
                                     ("Thu"4),
                                     ("Fri"5),
                                     ("Sat"6)]) {
            Some(v) => { tm.tm_wday = v; Ok(()) }
            None => Err(ParseError::InvalidDay)
        },
        'B' => match match_strs(s, &[("January"0),
                                     ("February"1),
                                     ("March"2),
                                     ("April"3),
                                     ("May"4),
                                     ("June"5),
                                     ("July"6),
                                     ("August"7),
                                     ("September"8),
                                     ("October"9),
                                     ("November"10),
                                     ("December"11)]) {
            Some(v) => { tm.tm_mon = v; Ok(()) }
            None => Err(ParseError::InvalidMonth)
        },
        'b' | 'h' => match match_strs(s, &[("Jan"0),
                                           ("Feb"1),
                                           ("Mar"2),
                                           ("Apr"3),
                                           ("May"4),
                                           ("Jun"5),
                                           ("Jul"6),
                                           ("Aug"7),
                                           ("Sep"8),
                                           ("Oct"9),
                                           ("Nov"10),
                                           ("Dec"11)]) {
            Some(v) => { tm.tm_mon = v; Ok(()) }
            None => Err(ParseError::InvalidMonth)
        },
        'C' => match match_digits_in_range(s, 12false099) {
            Some(v) => { tm.tm_year += (v * 100) - 1900; Ok(()) }
            None => Err(ParseError::InvalidYear)
        },
        'c' => {
            parse_type(s, 'a', tm)
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'b', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'e', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'T', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'Y', tm))
        }
        'D' | 'x' => {
            parse_type(s, 'm', tm)
                .and_then(|()| parse_char(s, '/'))
                .and_then(|()| parse_type(s, 'd', tm))
                .and_then(|()| parse_char(s, '/'))
                .and_then(|()| parse_type(s, 'y', tm))
        }
        'd' => match match_digits_in_range(s, 12false131) {
            Some(v) => { tm.tm_mday = v; Ok(()) }
            None => Err(ParseError::InvalidDayOfMonth)
        },
        'e' => match match_digits_in_range(s, 12true131) {
            Some(v) => { tm.tm_mday = v; Ok(()) }
            None => Err(ParseError::InvalidDayOfMonth)
        },
        'f' => {
            tm.tm_nsec = match_fractional_seconds(s);
            Ok(())
        }
        'F' => {
            parse_type(s, 'Y', tm)
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'm', tm))
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'd', tm))
        }
        'H' => {
            match match_digits_in_range(s, 12false023) {
                Some(v) => { tm.tm_hour = v; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'I' => {
            match match_digits_in_range(s, 12false112) {
                Some(v) => { tm.tm_hour = if v == 12 { 0 } else { v }; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'j' => {
            match match_digits_in_range(s, 13false1366) {
                Some(v) => { tm.tm_yday = v - 1; Ok(()) }
                None => Err(ParseError::InvalidDayOfYear)
            }
        }
        'k' => {
            match match_digits_in_range(s, 12true023) {
                Some(v) => { tm.tm_hour = v; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'l' => {
            match match_digits_in_range(s, 12true112) {
                Some(v) => { tm.tm_hour = if v == 12 { 0 } else { v }; Ok(()) }
                None => Err(ParseError::InvalidHour)
            }
        }
        'M' => {
            match match_digits_in_range(s, 12false059) {
                Some(v) => { tm.tm_min = v; Ok(()) }
                None => Err(ParseError::InvalidMinute)
            }
        }
        'm' => {
            match match_digits_in_range(s, 12false112) {
                Some(v) => { tm.tm_mon = v - 1; Ok(()) }
                None => Err(ParseError::InvalidMonth)
            }
        }
        'n' => parse_char(s, '\n'),
        'P' => match match_strs(s, &[("am"0), ("pm"12)]) {
            Some(v) => { tm.tm_hour += v; Ok(()) }
            None => Err(ParseError::InvalidHour)
        },
        'p' => match match_strs(s, &[("AM"0), ("PM"12)]) {
            Some(v) => { tm.tm_hour += v; Ok(()) }
            None => Err(ParseError::InvalidHour)
        },
        'R' => {
            parse_type(s, 'H', tm)
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'M', tm))
        }
        'r' => {
            parse_type(s, 'I', tm)
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'M', tm))
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'S', tm))
                .and_then(|()| parse_char(s, ' '))
                .and_then(|()| parse_type(s, 'p', tm))
        }
        's' => {
            match match_digits_i64(s, 118false) {
                Some(v) => {
                    *tm = at_utc(Timespec::new(v, 0));
                    Ok(())
                },
                None => Err(ParseError::InvalidSecondsSinceEpoch)
            }
        }
        'S' => {
            match match_digits_in_range(s, 12false060) {
                Some(v) => { tm.tm_sec = v; Ok(()) }
                None => Err(ParseError::InvalidSecond)
            }
        }
        //'s' {}
        'T' | 'X' => {
            parse_type(s, 'H', tm)
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'M', tm))
                .and_then(|()| parse_char(s, ':'))
                .and_then(|()| parse_type(s, 'S', tm))
        }
        't' => parse_char(s, '\t'),
        'u' => {
            match match_digits_in_range(s, 11false17) {
                Some(v) => { tm.tm_wday = if v == 7 { 0 } else { v }; Ok(()) }
                None => Err(ParseError::InvalidDayOfWeek)
            }
        }
        'v' => {
            parse_type(s, 'e', tm)
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'b', tm))
                .and_then(|()| parse_char(s, '-'))
                .and_then(|()| parse_type(s, 'Y', tm))
        }
        //'W' {}
        'w' => {
            match match_digits_in_range(s, 11false06) {
                Some(v) => { tm.tm_wday = v; Ok(()) }
                None => Err(ParseError::InvalidDayOfWeek)
            }
        }
        'Y' => {
            match match_digits(s, 44false) {
                Some(v) => { tm.tm_year = v - 1900; Ok(()) }
                None => Err(ParseError::InvalidYear)
            }
        }
        'y' => {
            match match_digits_in_range(s, 12false099) {
                Some(v) => { tm.tm_year = v; Ok(()) }
                None => Err(ParseError::InvalidYear)
            }
        }
        'Z' => {
            if match_str(s, "UTC") || match_str(s, "GMT") {
                tm.tm_utcoff = 0;
                Ok(())
            } else {
                // It's odd, but to maintain compatibility with c's
                // strptime we ignore the timezone.
                for (i, ch) in s.char_indices() {
                    if ch == ' ' {
                        *s = &s[i..];
                        return Ok(())
                    }
                }
                *s = "";
                Ok(())
            }
        }
        'z' => {
            if parse_char(s, 'Z').is_ok() {
                tm.tm_utcoff = 0;
                Ok(())
            } else {
                let sign = if parse_char(s, '+').is_ok() {1}
                           else if parse_char(s, '-').is_ok() {-1}
                           else { return Err(ParseError::InvalidZoneOffset) };

                let hours;
                let minutes;

                match match_digits(s, 22false) {
                    Some(h) => hours = h,
                    None => return Err(ParseError::InvalidZoneOffset)
                }

                // consume the colon if its present,
                // just ignore it otherwise
                let _ = parse_char(s, ':');

                match match_digits(s, 22false) {
                    Some(m) => minutes = m,
                    None => return Err(ParseError::InvalidZoneOffset)
                }

                tm.tm_utcoff = sign * (hours * 60 * 60 + minutes * 60);
                Ok(())
            }
        }
        '%' => parse_char(s, '%'),
        ch => Err(ParseError::InvalidFormatSpecifier(ch))
    }
}


fn match_str(s: &mut &str, needle: &str) -> bool {
    if s.starts_with(needle) {
        *s = &s[needle.len()..];
        true
    } else {
        false
    }
}

fn match_strs(ss: &mut &str, strs: &[(&str, i32)]) -> Option<i32> {
    for &(needle, value) in strs.iter() {
        if match_str(ss, needle) {
            return Some(value)
        }
    }
    None
}

fn match_digits(ss: &mut &str, min_digits : usize, max_digits: usize, ws: bool) -> Option<i32> {
    match match_digits_i64(ss, min_digits, max_digits, ws) {
        Some(v) => Some(v as i32),
        None => None
    }
}

fn match_digits_i64(ss: &mut &str, min_digits : usize, max_digits: usize, ws: bool) -> Option<i64> {
    let mut value : i64 = 0;
    let mut n = 0;
    if ws {
        #[allow(deprecated)] // use `trim_start_matches` starting in 1.30
        let s2 = ss.trim_left_matches(" ");
        n = ss.len() - s2.len();
        if n > max_digits { return None }
    }
    let chars = ss[n..].char_indices();
    for (_, ch) in chars.take(max_digits - n) {
        match ch {
            '0' ... '9' => value = value * 10 + (ch as i64 - '0' as i64),
            _ => break,
        }
        n += 1;
    }

    if n >= min_digits && n <= max_digits {
        *ss = &ss[n..];
        Some(value)
    } else {
        None
    }
}

fn match_fractional_seconds(ss: &mut &str) -> i32 {
    let mut value = 0;
    let mut multiplier = NSEC_PER_SEC / 10;

    let mut chars = ss.char_indices();
    let orig = *ss;
    for (i, ch) in &mut chars {
        *ss = &orig[i..];
        match ch {
            '0' ... '9' => {
                // This will drop digits after the nanoseconds place
                let digit = ch as i32 - '0' as i32;
                value += digit * multiplier;
                multiplier /= 10;
            }
            _ => break
        }
    }

    value
}

fn match_digits_in_range(ss: &mut &str,
                         min_digits : usize, max_digits : usize,
                         ws: bool, min: i32, max: i32) -> Option<i32> {
    let before = *ss;
    match match_digits(ss, min_digits, max_digits, ws) {
        Some(val) if val >= min && val <= max => Some(val),
        _ => { *ss = before; None }
    }
}

fn parse_char(s: &mut &str, c: char) -> Result<(), ParseError> {
    match s.char_indices().next() {
        Some((i, c2)) => {
            if c == c2 {
                *s = &s[i + c2.len_utf8()..];
                Ok(())
            } else {
                Err(ParseError::UnexpectedCharacter(c, c2))
            }
        }
        None => Err(ParseError::InvalidTime),
    }
}

Messung V0.5 in Prozent
C=98 H=97 G=97

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet am  2026-06-19) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik