fmemopen(3)

الاسم
fmemopen - فتح الذاكرة كدفق

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#include <stdio.h>

FILE *fmemopen(size_t size;
               void buf[size], size_t size, const char *mode);

    متطلبات ماكروات اختبار الميزات لـ glibc (انظر feature_test_macros(7)):

fmemopen():
    منذ glibc 2.10:
        _POSIX_C_SOURCE >= 200809L
    قبل glibc 2.10:
        _GNU_SOURCE

الوصف
تفتح الدالة fmemopen() دفقًا يسمح بالوصول المُحدد بواسطة mode. يسمح الدفق بإجراء الإدخال/الإخراج على سلسلة المحارف أو مخبأ الذاكرة المُشار إليه بواسطة buf.

يُحدد المعامل mode دلالات الإدخال/الإخراج على الدفق، وهو أحد التالي:

r   يُفتح الدفق للقراءة.

w   يُفتح الدفق للكتابة.

a   إلحاق؛ يُفتح الدفق للكتابة، مع تعيين موضع المخبأ المبدئي إلى أول بايت فارغ.

r+  يُفتح الدفق للقراءة والكتابة.

w+  يُفتح الدفق للقراءة والكتابة. تُقتطع محتويات المخبأ (أي، يُوضع '\0' في أول بايت من المخبأ).

a+  إلحاق؛ يُفتح الدفق للقراءة والكتابة، مع تعيين موضع المخبأ المبدئي إلى أول بايت فارغ.

يحتفظ الدفق بمفهوم الموضع الحالي، وهو الموقع الذي ستُجرى فيه عملية الإدخال/الإخراج التالية. يُحدّث الموضع الحالي ضمنيًا بواسطة عمليات الإدخال/الإخراج. يمكن تحديثه صراحةً باستخدام fseek(3)، وتحديده باستخدام ftell(3). في جميع الأوضاع عدا الإلحاق، يُعيّن الموضع المبدئي إلى بداية المخبأ. في وضع الإلحاق، إذا لم يُعثر على بايت فارغ داخل المخبأ، فإن الموضع المبدئي يكون size+1.

إذا حُدد buf كـ NULL، فإن fmemopen() تخصص مخبأً بحجم size بايت. هذا مفيد لتطبيق يريد كتابة بيانات إلى مخبأ مؤقت ثم قراءتها مرة أخرى. يُعيّن الموضع المبدئي إلى بداية المخبأ. يُحرّر المخبأ آليًا عند إغلاق الدفق. لاحظ أنه لا توجد طريقة للمتصل للحصول على مؤشر إلى المخبأ المؤقت المُخصص بواسطة هذه الاستدعاء (لكن انظر open_memstream(3)).

إذا لم يكن buf NULL، فيجب أن يشير إلى مخبأ بحجم size بايت على الأقل مُخصص بواسطة المتصل.

عندما يُمسح دفق فُتح للكتابة (fflush(3)) أو يُغلق (fclose(3))، يُكتب بايت فارغ في نهاية المخبأ إذا وُجدت مساحة. يجب على المتصل ضمان توفر بايت إضافي في المخبأ (وأن size يحسب ذلك البايت) للسماح بذلك.

في دفق فُتح للقراءة، لا تتسبب البايتات الفارغة ('\0') في المخبأ في إرجاع عمليات القراءة لإشارة نهاية الملف. ستشير قراءة من المخبأ إلى نهاية الملف فقط عندما يتقدم موضع المخبأ الحالي size بايت بعد بداية المخبأ.

تحدث عمليات الكتابة إما في الموضع الحالي (للأوضاع غير الإلحاق)، أو في الحجم الحالي للدفق (لوضع الإلحاق).

تؤدي محاولات كتابة أكثر من size بايت إلى المخبأ إلى خطأ. مبدئيًا، ستكون هذه الأخطاء مرئية (بغياب البيانات) فقط عند مسح مخبأ stdio. قد يكون تعطيل التخزين المؤقت بالاستدعاء التالي مفيدًا لاكتشاف الأخطاء في وقت عملية الإخراج:

    setbuf(stream, NULL);

قيمة الإرجاع
عند الإكمال بنجاح، تُرجع fmemopen() مؤشر FILE. وإلا، يُرجع NULL ويُعيّن errno للإشارة إلى الخطأ.

السمات
للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر attributes(7).
الواجهة | السمة | القيمة
fmemopen()، | سلامة الخيوط | MT-Safe

المعايير
POSIX.1-2008.

التاريخ
glibc 1.0.x. POSIX.1-2008.

يحدد POSIX.1-2008 أن 'b' في mode يجب تجاهله. ومع ذلك، يعدل التصحيح التقني 1 المعيار للسماح بمعالجة خاصة بالتنفيذ لهذه الحالة، مما يسمح بمعالجة glibc لـ 'b'.

مع glibc 2.22، أُزيل الوضع الثنائي (انظر أدناه)، وثُبتت العديد من الأخطاء القديمة في تنفيذ fmemopen()، وأُنشئ رمز جديد مُرقّم لهذه الواجهة.

  الوضع الثنائي
من glibc 2.9 إلى glibc 2.21، دعم تنفيذ glibc لـ fmemopen() وضعًا "ثنائيًا"، يُفعّل بتحديد الحرف 'b' كالحرف الثاني في mode. في هذا الوضع، لا تُضيف عمليات الكتابة ضمنيًا بايت فارغ ختامي، ويكون fseek(3) SEEK_END نسبيًا لنهاية المخزن المؤقت (أي القيمة المحددة بواسطة وسيط size)، بدلاً من طول السلسلة الحالي.

أصاب خطأ API تنفيذ الوضع الثنائي: لتحديد الوضع الثنائي، يجب أن يكون 'b' الحرف الثاني في mode. وبالتالي، على سبيل المثال، "wb+" له التأثير المطلوب، لكن "w+b" ليس له. هذا غير متسق مع معالجة mode بواسطة fopen(3).

أُزيل الوضع الثنائي في glibc 2.22؛ ليس لـ 'b' المحدد في mode أي تأثير.

ملاحظات
لا يوجد واصف ملف مرتبط بدفق الملف المُعاد بواسطة هذه الدالة (أي، سيعيد fileno(3) خطأً إذا استُدعي على الدفق المُعاد).

العلل
قبل glibc 2.22، إذا حُدد size كصفر، يفشل fmemopen() مع الخطأ EINVAL. سيكون أكثر اتساقًا إذا أنشأت هذه الحالة بنجاح دفقًا يعيد بعد ذلك نهاية الملف عند أول محاولة قراءة؛ منذ glibc 2.22، يوفر تنفيذ glibc هذا السلوك.

قبل glibc 2.22، تحديد وضع الإلحاق ("a" أو "a+") لـ fmemopen() يضبط موضع المخزن المؤقت المبدئي على أول بايت فارغ، لكن (إذا أُعيد ضبط الموضع الحالي إلى موقع غير نهاية الدفق) لا يُجبر عمليات الكتابة اللاحقة على الإلحاق في نهاية الدفق. ثُبت هذا الخطأ في glibc 2.22.

قبل glibc 2.22، إذا حدد وسيط mode لـ fmemopen() الإلحاق ("a" أو "a+")، ولا يغطي وسيط size بايتًا فارغًا في buf، فوفقًا لـ POSIX.1-2008، يجب ضبط موضع المخزن المؤقت المبدئي على البايت التالي بعد نهاية المخزن المؤقت. ومع ذلك، في هذه الحالة يضبط glibc fmemopen() موضع المخزن المؤقت على -1. ثُبت هذا الخطأ في glibc 2.22.

قبل glibc 2.22، عندما أُجري استدعاء لـ fseek(3) بقيمة whence من SEEK_END على دفق أُنشئ بواسطة fmemopen()، كان offset يُطرح من موضع نهاية الدفق، بدلاً من أن يُضاف. ثُبت هذا الخطأ في glibc 2.22.

غيّرت إضافة glibc 2.9 للوضع "الثنائي" لـ fmemopen() ABI بصمت: سابقًا، تجاهل fmemopen() 'b' في mode.

أمثلة
يستخدم البرنامج أدناه fmemopen() لفتح مخزن إدخال مؤقت، و open_memstream(3) لفتح مخزن إخراج مؤقت ذي حجم ديناميكي. يمسح البرنامج سلسلة إدخاله (المأخوذة من وسيط سطر الأوامر الأول للبرنامج) لقراءة الأعداد الصحيحة، ويكتب مربعات هذه الأعداد الصحيحة إلى مخزن الإخراج المؤقت. مثال على المخرجات التي ينتجها هذا البرنامج هو التالي:

    $ ./a.out '1 23 43'
    size=11; ptr=1 529 1849

  مصدر البرنامج
    #define _GNU_SOURCE
    #include <err.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    int
    main(int argc, char *argv[])
    {
        FILE *out, *in;
        int v, s;
        size_t size;
        char *ptr;

        if (argc != 2) {
            fprintf(stderr, "Usage: %s '<num>...'\n", argv[0]);
            exit(EXIT_FAILURE);
        }

        in = fmemopen(argv[1], strlen(argv[1]), "r");
        if (in == NULL)
            err(EXIT_FAILURE, "fmemopen");

        out = open_memstream(&ptr, &size);
        if (out == NULL)
            err(EXIT_FAILURE, "open_memstream");

        for (;;) {
            s = fscanf(in, "%d", &v);
            if (s <= 0)
                break;

            s = fprintf(out, "%d ", v * v);
            if (s == -1)
                err(EXIT_FAILURE, "fprintf");
        }

        fclose(in);
        fclose(out);

        printf("size=%zu; ptr=%s\n", size, ptr);

        free(ptr);
        exit(EXIT_SUCCESS);
    }

انظر أيضًا
fopen(3)، fopencookie(3)، open_memstream(3)

ترجمة
تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.