Не работает поиск, по списку, перенесенный из си. В чем различия работы обеих функций?

152
03 июня 2021, 11:30

В модуле libavi_plugin из состава VLC, присутствует следующий поиск по списку чанков:

void *AVI_ChunkFind_( avi_chunk_t *p_chk,
                      vlc_fourcc_t i_fourcc, int i_number, bool b_list )
{
    if( !p_chk )
        return NULL;
    for( avi_chunk_t *p_child = p_chk->common.p_first;
                      p_child; p_child = p_child->common.p_next )
    {
        if( b_list && p_child->list.i_type == 0 )
            continue;
        if( p_child->common.i_chunk_fourcc != i_fourcc &&
            (!b_list || p_child->list.i_type != i_fourcc) )
            continue;
        if( i_number-- == 0 )
            return p_child; /* We found it */
    }
    return NULL;
}

И я его перевел на c#, мало изменений, т.к. работаю через неуправляемую память:

[StructLayout(LayoutKind.Sequential)]
public unsafe struct AviChunkCommon
{
    public Fcc ChunkFcc;
    public ulong Size;
    public ulong Position;
    public AviChunk* Next;
    public AviChunk* Father;
    public AviChunk* First;
}
[StructLayout(LayoutKind.Explicit)]
public struct AviChunk
{
    [FieldOffset(0)]
    public AviChunkCommon Common;
    [FieldOffset(0)]
    public AviChunkList List;
    [FieldOffset(0)]
    public AviChunkIdx1 Idx1;
    [FieldOffset(0)]
    public AviChunkAvih Avih;
    [FieldOffset(0)]
    public AviChunkStrh Strh;
    [FieldOffset(0)]
    public AviChunkStrf Strf;
    [FieldOffset(0)]
    public AviChunkStrd Strd;
    [FieldOffset(0)]
    public AviChunkVprp Vprp;
    [FieldOffset(0)]
    public AviChunkIndx Index;
    [FieldOffset(0)]
    public AviChunkString String;
    public ulong Size => ((Common.Size + 1u) & ~1u) + 8;
    public ulong End => Common.Position + Size;
}
private static AviChunk* ChunkFind(AviChunk* chunk, Fcc fcc, int number, bool list)
{
    if (chunk == null)
    {
        return null;
    }
    for (AviChunk* pChild = chunk->Common.First;
                   pChild != null; pChild = pChild->Common.Next)
    {
        if (list && pChild->List.Type == 0u)
        {
            continue;
        }
        if (pChild->Common.ChunkFcc != fcc &&
              (!list || pChild->List.Type != fcc))
        {
            continue;
        }
        if ((--number) == 0) // We found it!
        {
            return pChild;
        }
    }
    return null;
}

Но этот поиск на c#, ведет себя не так как на си. Если необходимый элемент находится в chunk, то он его находит, но если он находится глубже, то не не найдет.

Подскажите в чем различие работы кода на c# и почему он ведет себя не так как я предполагаю?

При этом, я уверен в том что там есть необходимые данные, вот дамп списка:

* LIST-root size: 810026560 pos: 0
    + RIFF-AVI  size: 810026552 pos: 0
        + LIST-hdrl size: 8898 pos: 12
            + avih size: 56 pos: 24
            + LIST-strl size: 4316 pos: 88
                + strh size: 56 pos: 100
            + JUNK size: 4116 pos: 212
            + vprp size: 68 pos: 4336
            + LIST-strl size: 4230 pos: 4412
            + strh size: 56 pos: 4424
        + JUNK size: 4116 pos: 4526
        + JUNK size: 260 pos: 8650
        + LIST-INFO size: 34 pos: 8918
        + ISFT size: 22 pos: 8930
        + JUNK size: 1016 pos: 8960
        + LIST-movi size: 802487072 pos: 9984
        + idx1 size: 7529488 pos: 802497064
Answer 1

Вот ошибка

if ((--number) == 0) // We found it!

исходный код

if( i_number-- == 0 )
      return p_child; /* We found it */

читается так

int tmp = i_number;
i_number = i_number - 1;
if (tmp == 0)
  return p_child; /* We found it */

А вы зачем-то суффиксный декремент заменили префиксным и получили

i_number = i_number - 1;
if (i_number == 0)
  return p_child; /* We found it */
READ ALSO
Как сделать релизную сборку программы, написанной на C# в Visual Studio 2019?

Как сделать релизную сборку программы, написанной на C# в Visual Studio 2019?

Программа рабочая, хочу сделать сборку, создать установщик (в этом опыт есть) и дальше опубликовать на SourceForge и тп

126
Как получить доступ к елементу из StackLayout в Xamarin?

Как получить доступ к елементу из StackLayout в Xamarin?

Как можно сделать так,что бы при изменении текста в entry текст копировался в label? В примере в книге элементы располагаются в ContentPage и к ним можно...

197
Обобщающий класс

Обобщающий класс

У меня есть 3 класса, допустим

101