81

Re: Кодофлуд, або флудокод

        If String.IsNullOrEmpty(jr) Then Exit Sub

        Dim objJsonSerializer = New Runtime.Serialization.Json.DataContractJsonSerializer _
        (GetType(MyJSON.PostData))

        Dim r2 = New IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(jr))

        Dim nw = CType(objJsonSerializer.ReadObject(r2), MyJSON.PostData)
        If IsNothing(nw.post) Then
            RaiseEvent ErrorEvent("Обкʼєкт запису = Nothing. Текст від серверу: " & jr & " ID запису: " & IDЗапису)
            Exit Sub
        End If
        Dim IDПридатнийДляФайловоїСистеми$ = String.Empty

        IDПридатнийДляФайловоїСистеми = _
        System.Text.RegularExpressions.Regex.Replace(nw.post.id, "[\\/:\*\?""<>\|\x00-\x1F]", "")

        Select Case UCase(IDПридатнийДляФайловоїСистеми)
            Case "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"
                IDПридатнийДляФайловоїСистеми = String.Empty
        End Select

        Dim назваФайлуАбоПапкиДляЗбереження$ = String.Empty
        Dim часСтворенняДляНазвиФайлуДляЗбереження As Date

        If DateTime.TryParse(nw.post.created, часСтворенняДляНазвиФайлуДляЗбереження) Then
            назваФайлуАбоПапкиДляЗбереження = часСтворенняДляНазвиФайлуДляЗбереження.ToShortDateString.Replace(":", ".").Replace("/", ".").Replace("\", ".").Replace("|", ".") & _
            " " & часСтворенняДляНазвиФайлуДляЗбереження.ToLongTimeString.Replace(":", ".").Replace("/", ".").Replace("\", ".").Replace("|", ".")
        End If

        If IDПридатнийДляФайловоїСистеми <> String.Empty Then
            назваФайлуАбоПапкиДляЗбереження &= " " & IDПридатнийДляФайловоїСистеми
        End If

        If назваФайлуАбоПапкиДляЗбереження = String.Empty Then
            назваФайлуАбоПапкиДляЗбереження = Date.Now.ToString.Replace(":", ".").Replace("/", ".").Replace("\", ".").Replace("|", ".")
        End If

        If nw.post.private Then
            назваФайлуАбоПапкиДляЗбереження &= " private"
        End If

        Dim коментаріЗгрупованіПоto_comment_id = _
        New Dictionary(Of UInteger, List(Of UInteger))

        For i = 0 To nw.comments.Count - 1
            If nw.comments(i).to_comment_id.HasValue Then
                If коментаріЗгрупованіПоto_comment_id.ContainsKey _
                (nw.comments(i).to_comment_id.Value) Then
                    коментаріЗгрупованіПоto_comment_id.Item(nw.comments(i).to_comment_id.Value).Add(nw.comments(i).id)
                Else
                    коментаріЗгрупованіПоto_comment_id.Add(nw.comments(i).to_comment_id.Value, New List(Of UInteger))
                    коментаріЗгрупованіПоto_comment_id.Item(nw.comments(i).to_comment_id.Value).Add(nw.comments(i).id)
                End If
            End If
        Next

        Dim деревоКоментарів$ = String.Empty
        Dim visited As List(Of UInteger) = New List(Of UInteger)

        For i = 0 To nw.comments.Count - 1
            If nw.comments(i).to_comment_id.HasValue = False Then
                деревоКоментарів &= "<LI><SPAN class=comment-text>" & ЗамінитиЗарезервованіВHTMLСимволи(nw.comments(i).text) & "</SPAN></LI>" & vbCrLf & _
                РозмітитиДаніПроКоментар(ОтриматиКоментарПоID(nw.comments(i).id, nw.comments))
            End If

            Dim IDКоментаря As UInteger = nw.comments(i).id

            If visited.Contains(IDКоментаря) Then Continue For
            Dim vi As New List(Of Dictionary(Of UInteger, UInteger))

            Dim ul = String.Empty

            Dim iv = 0UI
            Dim index = iv
            Dim localvisited = visited
l1:
            If коментаріЗгрупованіПоto_comment_id.ContainsKey(IDКоментаря) Then
                If iv > коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Count - 1 Then
                    iv = 0
                End If
                For index = iv To коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Count - 1
                    If коментаріЗгрупованіПоto_comment_id.ContainsKey(коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Item(index)) Then
                        деревоКоментарів &= vbCrLf & "<UL><LI><SPAN class=comment-text>" & ЗамінитиЗарезервованіВHTMLСимволи(ОтриматиКоментарПоID(коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Item(index), nw.comments).text) & "</SPAN>" & _
                        РозмітитиДаніПроКоментар(ОтриматиКоментарПоID(коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Item(index), nw.comments)) & "</LI>"
                        If visited.Contains(IDКоментаря) = False Then
                            visited.Add(IDКоментаря)
                        End If

                        If коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Count - 1 > index Then
                            Dim індексНаступногоКоментаря As UInteger
                            If index + 1 > коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Count - 1 Then
                                індексНаступногоКоментаря = index
                            Else
                                індексНаступногоКоментаря = index + 1
                            End If
                            Dim tmpd = New Dictionary(Of UInteger, UInteger)
                            tmpd.Add(IDКоментаря, індексНаступногоКоментаря)
                            vi.Add(tmpd)
                        Else
                            ul &= "</UL>" & vbCrLf
                        End If

                        IDКоментаря = коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Item(index)

                        GoTo l1
                    ElseIf ОтриматиКоментарПоID(коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Item(index), nw.comments).to_comment_id.HasValue Then
                        деревоКоментарів &= "<UL><LI><SPAN class=comment-text>" & ЗамінитиЗарезервованіВHTMLСимволи(ОтриматиКоментарПоID(коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Item(index), nw.comments).text) & "</SPAN>" & _
                        РозмітитиДаніПроКоментар(ОтриматиКоментарПоID(коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Item(index), nw.comments)) & "</LI></UL>" & vbCrLf
                        If visited.Contains(IDКоментаря) = False Then
                            visited.Add(IDКоментаря)
                        End If

                        If index <> коментаріЗгрупованіПоto_comment_id.Item(IDКоментаря).Count - 1 Then
                            iv = index + 1
                            GoTo l1
                        End If
                        деревоКоментарів &= ul
                        ul = String.Empty
                    End If
                Next
            End If
            If vi.Count > 0 Then
                IDКоментаря = vi.Last.Last.Key
                iv = vi.Last.Last.Value
                vi.Remove(vi.Last)
                ul &= "</UL>" & vbCrLf
                GoTo l1
            End If
        Next
        If деревоКоментарів <> String.Empty Then
            деревоКоментарів = "<FIELDSET><LEGEND>Коментарі</LEGEND><UL>" & vbCrLf & деревоКоментарів & vbCrLf & "</UL></FIELDSET>"
        End If

82

Re: Кодофлуд, або флудокод

Тепер, якщо мені хтось буде втирати що в коді не можна лишати goto, буду посилати на репо raspberrypi/linux/blob/rpi-6.12.y/drivers/nvme/host/pci.c.

raspberrypi (drivers/nvme/host/pci.c) написав:
static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
        u32 chunk_size)
{
    struct nvme_host_mem_buf_desc *descs;
    u32 max_entries, len, descs_size;
    dma_addr_t descs_dma;
    int i = 0;
    void **bufs;
    u64 size, tmp;

    tmp = (preferred + chunk_size - 1);
    do_div(tmp, chunk_size);
    max_entries = tmp;

    if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries)
        max_entries = dev->ctrl.hmmaxd;

    descs_size = max_entries * sizeof(*descs);
    descs = dma_alloc_coherent(dev->dev, descs_size, &descs_dma,
            GFP_KERNEL);
    if (!descs)
        goto out;

    bufs = kcalloc(max_entries, sizeof(*bufs), GFP_KERNEL);
    if (!bufs)
        goto out_free_descs;

    for (size = 0; size < preferred && i < max_entries; size += len) {
        dma_addr_t dma_addr;

        len = min_t(u64, chunk_size, preferred - size);
        bufs[i] = dma_alloc_attrs(dev->dev, len, &dma_addr, GFP_KERNEL,
                DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
        if (!bufs[i])
            break;

        descs[i].addr = cpu_to_le64(dma_addr);
        descs[i].size = cpu_to_le32(len / NVME_CTRL_PAGE_SIZE);
        i++;
    }

    if (!size)
        goto out_free_bufs;

    dev->nr_host_mem_descs = i;
    dev->host_mem_size = size;
    dev->host_mem_descs = descs;
    dev->host_mem_descs_dma = descs_dma;
    dev->host_mem_descs_size = descs_size;
    dev->host_mem_desc_bufs = bufs;
    return 0;

out_free_bufs:
    while (--i >= 0) {
        size_t size = le32_to_cpu(descs[i].size) * NVME_CTRL_PAGE_SIZE;

        dma_free_attrs(dev->dev, size, bufs[i],
                   le64_to_cpu(descs[i].addr),
                   DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
    }

    kfree(bufs);
out_free_descs:
    dma_free_coherent(dev->dev, descs_size, descs, descs_dma);
out:
    dev->host_mem_descs = NULL;
    return -ENOMEM;
}

83

Re: Кодофлуд, або флудокод

leofun01 написав:

Тепер, якщо мені хтось буде втирати що в коді не можна лишати goto, буду посилати на репо raspberrypi/linux/blob/rpi-6.12.y/drivers/nvme/host/pci.c.

Цікаво, чим був викликаний вибір саме цього файлу.
Для лінукса це стандартний метод звільнення захоплених ресурсів при ранньому виході по помилках.
Як на мене, зручно перевіряти парність і тримати послідовність.

А якщо помилка трапилася до того, як щось виділили/захопили, то return відразу.

https://replace.org.ua/extensions/om_images/img/68b42fcd869bf/c1524b14f5412a688f0c2affcf476bdd.png

p.s. Там з goto є дійсно криві місця, як не забуду і знайду, то покажу.

Подякували: wander1

84

Re: Кодофлуд, або флудокод

Не можу знайти саме те місце. Щось типу цього переходу на begin: (тут і ще в одній функції), але з середини while() назад на тіло if(). Десь в тих же краях було.
Втім, може те місце переписали.
А загалом переходи назад на мітку again: чи begin: чи подібну зустріxаються, але не так часто на тлі goto звільнення русурсів після помилок.
І рідше, ніж щось в дусі

    case 8 ... 15:

85

Re: Кодофлуд, або флудокод

leofun01 написав:

Тепер, якщо мені хтось буде втирати що в коді не можна лишати goto, буду посилати на репо raspberrypi/linux/blob/rpi-6.12.y/drivers/nvme/host/pci.c.

raspberrypi (drivers/nvme/host/pci.c) написав:
static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
        u32 chunk_size)
{
    struct nvme_host_mem_buf_desc *descs;
    u32 max_entries, len, descs_size;
    dma_addr_t descs_dma;
    int i = 0;
    void **bufs;
    u64 size, tmp;

    tmp = (preferred + chunk_size - 1);
    do_div(tmp, chunk_size);
    max_entries = tmp;

    if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries)
        max_entries = dev->ctrl.hmmaxd;

    descs_size = max_entries * sizeof(*descs);
    descs = dma_alloc_coherent(dev->dev, descs_size, &descs_dma,
            GFP_KERNEL);
    if (!descs)
        goto out;

    bufs = kcalloc(max_entries, sizeof(*bufs), GFP_KERNEL);
    if (!bufs)
        goto out_free_descs;

    for (size = 0; size < preferred && i < max_entries; size += len) {
        dma_addr_t dma_addr;

        len = min_t(u64, chunk_size, preferred - size);
        bufs[i] = dma_alloc_attrs(dev->dev, len, &dma_addr, GFP_KERNEL,
                DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
        if (!bufs[i])
            break;

        descs[i].addr = cpu_to_le64(dma_addr);
        descs[i].size = cpu_to_le32(len / NVME_CTRL_PAGE_SIZE);
        i++;
    }

    if (!size)
        goto out_free_bufs;

    dev->nr_host_mem_descs = i;
    dev->host_mem_size = size;
    dev->host_mem_descs = descs;
    dev->host_mem_descs_dma = descs_dma;
    dev->host_mem_descs_size = descs_size;
    dev->host_mem_desc_bufs = bufs;
    return 0;

out_free_bufs:
    while (--i >= 0) {
        size_t size = le32_to_cpu(descs[i].size) * NVME_CTRL_PAGE_SIZE;

        dma_free_attrs(dev->dev, size, bufs[i],
                   le64_to_cpu(descs[i].addr),
                   DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
    }

    kfree(bufs);
out_free_descs:
    dma_free_coherent(dev->dev, descs_size, descs, descs_dma);
out:
    dev->host_mem_descs = NULL;
    return -ENOMEM;
}

Посилання на жодний репо не матиме жодного сенсу, якщо ви самостійно не зможете обґрунтувати необхідність використання.

Прихований текст

Посилатись на те, як робить хтось -- не (завжди) означає, що варто робити так само.

86

Re: Кодофлуд, або флудокод

Це C, без деструкторів і виключних ситуацій. І всі переходи, зауважу, вперед, що практично унеможливлює спагетіфікацію.
Ключове питання використання goto - це те, що він робить код незрозумілим. Тут якраз навпаки.

87

Re: Кодофлуд, або флудокод

Goto до секції обробки помилки — якраз правильний шлях оформлення сішного коду. Здається, ще для виходу з багаторівневих циклів вважається припустимим. У решті випадків вважається антипатерном.