예제 #1
0
history_item_t history_t::item_at_index(size_t idx) {
    scoped_lock locker(lock);
    
    /* 0 is considered an invalid index */
    assert(idx > 0);
    idx--;
    
    /* idx=0 corresponds to last item in new_items */
    size_t new_item_count = new_items.size();
    if (idx < new_item_count) {
        return new_items.at(new_item_count - idx - 1);
    }
    
    /* Now look in our old items */
    idx -= new_item_count;
    load_old_if_needed();
    size_t old_item_count = old_item_offsets.size();
    if (idx < old_item_count) {
        /* idx=0 corresponds to last item in old_item_offsets */
        size_t offset = old_item_offsets.at(old_item_count - idx - 1);
        return history_t::decode_item(mmap_start + offset, mmap_length - offset);
    }
    
    /* Index past the valid range, so return an empty history item */
    return history_item_t(wcstring(), 0);
}
예제 #2
0
history_item_t history_t::decode_item(const char *base, size_t len, history_file_type_t type) {
    switch (type) {
        case history_type_fish_1_x: return history_t::decode_item_fish_1_x(base, len);
        case history_type_fish_2_0: return history_t::decode_item_fish_2_0(base, len);
        default: return history_item_t(L"");
    }
}
예제 #3
0
history_item_t history_t::decode_item(const char *base, size_t len) {
    wcstring cmd;
    time_t when = 0;
    path_list_t paths;
    
    size_t indent = 0, cursor = 0;
    std::string key, value, line;
    
    /* Read the "- cmd:" line */
    size_t advance = read_line(base, cursor, len, line);
    trim_leading_spaces(line);
    if (! extract_prefix(key, value, line) || key != "- cmd")
        goto done;
    
    cursor += advance;
    cmd = str2wcstring(value);

    /* Read the remaining lines */
    for (;;) {
        /* Read a line */
        size_t advance = read_line(base, cursor, len, line);
        
        /* Count and trim leading spaces */
        size_t this_indent = trim_leading_spaces(line);
        if (indent == 0)
            indent = this_indent;
        
        if (this_indent == 0 || indent != this_indent)
            break;
        
        if (! extract_prefix(key, value, line))
            break;
            
        /* We are definitely going to consume this line */
        unescape_yaml(value);
        cursor += advance;
        
        if (key == "when") {
            /* Parse an int from the timestamp */
            long tmp = 0;
            if (sscanf(value.c_str(), "%ld", &tmp) > 0) {
                when = tmp;
            }
        } else if (key == "paths") {
            /* Read lines starting with " - " until we can't read any more */
            for (;;) {
                size_t advance = read_line(base, cursor, len, line);
                if (trim_leading_spaces(line) <= indent)
                    break;
                    
                if (strncmp(line.c_str(), "- ", 2))
                    break;
                    
                /* We're going to consume this line */
                cursor += advance;
                

                /* Skip the leading dash-space and then store this path it */
                line.erase(0, 2);
                unescape_yaml(line);
                paths.push_front(str2wcstring(line));
            }
        }
    }
    /* Reverse the paths, since we pushed them to the front each time */
done:
    paths.reverse();
    return history_item_t(cmd, when, paths);
    
}
예제 #4
0
void history_t::add(const wcstring &str, const path_list_t &valid_paths)
{
    this->add(history_item_t(str, time(NULL), valid_paths));
}
예제 #5
0
/* Decode an item via the fish 1.x format. Adapted from fish 1.x's item_get(). */
history_item_t history_t::decode_item_fish_1_x(const char *begin, size_t length) {

    const char *end = begin + length;
    const char *pos=begin;

    bool was_backslash = 0;
    wcstring out;
    bool first_char = true;
    bool timestamp_mode = false;
    time_t timestamp = 0;
    
    while( 1 )
    {
        wchar_t c;
        mbstate_t state;
        size_t res;

        memset( &state, 0, sizeof(state) );

        res = mbrtowc( &c, pos, end-pos, &state );

        if( res == (size_t)-1 )
        {
            pos++;
            continue;
        }
        else if( res == (size_t)-2 )
        {
            break;
        }
        else if( res == (size_t)0 )
        {
            pos++;
            continue;
        }
        pos += res;

        if( c == L'\n' )
        {
            if( timestamp_mode )
            {
                const wchar_t *time_string = out.c_str();
                while( *time_string && !iswdigit(*time_string))
                    time_string++;
                errno=0;

                if( *time_string )
                {
                    time_t tm;
                    wchar_t *end;

                    errno = 0;
                    tm = (time_t)wcstol( time_string, &end, 10 );

                    if( tm && !errno && !*end )
                    {
                        timestamp = tm;
                    }

                }

                out.clear();
                timestamp_mode = false;
                continue;
            }
            if( !was_backslash )
                break;
        }

        if( first_char )
        {
            if( c == L'#' )
                timestamp_mode = true;
        }

        first_char = false;

        out.push_back(c);

        was_backslash = ( (c == L'\\') && !was_backslash);

    }
    
    out = history_unescape_newlines_fish_1_x(out);
    return history_item_t(out, timestamp);
}