"struct" --- 패킹 된 바이너리 데이터로 바이트열을 해석
******************************************************

**소스 코드:** Lib/struct.py

======================================================================

이 모듈은 파이썬 값과 파이썬 "bytes" 객체로 표현되는 C 구조체 사이의
변환을 수행합니다. 다른 소스 중에서도, 파일에 저장되었거나 네트워크 연
결에서 온 바이너리 데이터를 처리하는 데 사용할 수 있습니다. 포맷 문자
열을 구조체의 배치와 파이썬 값과의 변환에 대한 간결한 기술로 사용합니
다.

참고:

  기본적으로, 주어진 C 구조체를 패킹한 결과에는 관련된 C형에 대한 적절
  한 정렬(alignment)을 유지하기 위해 패드(pad) 바이트가 포함됩니다; 마
  찬가지로, 언 패킹할 때 정렬이 고려됩니다. 이 동작은 패킹 된 구조체의
  바이트열이 해당 C 구조체의 메모리 배치와 정확히 일치하도록 선택됩니
  다. 플랫폼 독립적인 데이터 형식을 처리하거나 묵시적 패드 바이트를 생
  략하려면, "native" 크기와 정렬 대신 "standard" 크기와 정렬을 사용하
  십시오: 자세한 내용은 바이트 순서, 크기 및 정렬을 참조하십시오.

여러 "struct" 함수(그리고 "Struct" 의 메서드)는 *buffer* 인자를 취합니
다. 이는 버퍼 프로토콜을 구현하고 읽을 수 있거나 읽고 쓸 수 있는 버퍼
를 제공하는 객체를 나타냅니다. 이 목적으로 사용되는 가장 일반적인 형은
"bytes"와 "bytearray"지만, 바이트 배열로 볼 수 있는 많은 다른 형이 버
퍼 프로토콜을 구현하므로, "bytes" 객체에서 추가로 복사하지 않고도 읽고
채울 수 있습니다.


함수와 예외
===========

이 모듈은 다음과 같은 예외와 함수를 정의합니다:

exception struct.error

   여러 상황에서 발생하는 예외; 인자는 무엇이 잘못되었는지 설명하는 문
   자열입니다.

struct.pack(format, v1, v2, ...)

   *v1*, *v2*, ... 값을 포함하고 포맷 문자열 *format*에 따라 패킹 된
   바이트열 객체를 반환합니다. 인자는 포맷이 요구하는 값과 정확히 일치
   해야 합니다.

struct.pack_into(format, buffer, offset, v1, v2, ...)

   포맷 문자열 *format*에 따라 값 *v1*, *v2*, ... 를 패킹하고 패킹 된
   바이트열을 쓰기 가능한 버퍼 *buffer*에 *offset* 위치에서부터 씁니다
   . *offset*은 필수 인자임에 유의하십시오.

struct.unpack(format, buffer)

   포맷 문자열 *format*에 따라 버퍼 *buffer*(아마도 "pack(format,
   ...)"으로 패킹 된)에서 언 패킹 합니다. 정확히 하나의 항목을 포함하
   더라도 결과는 튜플입니다. 바이트 단위의 버퍼 크기는 ("calcsize()"에
   의해 반영되는) 포맷이 요구하는 크기와 일치해야 합니다.

struct.unpack_from(format, /, buffer, offset=0)

   포맷 문자열 *format*에 따라, *offset* 위치에서 시작하여 *buffer*에
   서 언 패킹 합니다. 정확히 하나의 항목을 포함하더라도 결과는 튜플입
   니다. *offset* 위치에서 시작하여 바이트 단위로 측정한 버퍼 크기는
   ("calcsize()"에 의해 반영되는) 포맷이 요구하는 크기 이상이어야 합니
   다.

struct.iter_unpack(format, buffer)

   포맷 문자열 *format*에 따라 버퍼 *buffer*에서 이터레이션을 통해 언
   패킹 합니다. 이 함수는 모든 내용이 소비될 때까지 버퍼에서 같은 크기
   의 청크를 읽는 이터레이터를 반환합니다. 바이트 단위의 버퍼 크기는
   ("calcsize()"에 의해 반영되는) 포맷이 요구하는 크기의 배수여야 합니
   다.

   각 이터레이션은 포맷 문자열에 지정된 대로 튜플을 산출합니다.

   버전 3.4에 추가.

struct.calcsize(format)

   포맷 문자열 *format*에 해당하는 구조체("pack(format, ...)"에 의해
   생성되는 바이트열 객체)의 크기를 반환합니다.


포맷 문자열
===========

포맷 문자열은 데이터를 패킹과 언 패킹할 때 기대되는 배치를 지정하는 데
사용되는 메커니즘입니다. 이들은 패킹/언 패킹 될 데이터형을 지정하는 포
맷 문자로 구축됩니다. 또한, 바이트 순서, 크기 및 정렬을 제어하기 위한
특수 문자가 있습니다.


바이트 순서, 크기 및 정렬
-------------------------

기본적으로, C형은 기계의 네이티브 형식과 바이트 순서로 표현되며, 필요
하면 (C 컴파일러에서 사용하는 규칙에 따라) 패드 바이트로 건너뛰어 적절
하게 정렬됩니다.

또는, 다음 표에 따라, 포맷 문자열의 첫 번째 문자를 사용하여 패킹 된 데
이터의 바이트 순서, 크기 및 정렬을 표시할 수 있습니다:

+-------------+--------------------------+------------+-------------+
| 문자        | 바이트 순서              | 크기       | 정렬        |
|=============|==========================|============|=============|
| "@"         | 네이티브                 | 네이티브   | 네이티브    |
+-------------+--------------------------+------------+-------------+
| "="         | 네이티브                 | 표준       | none        |
+-------------+--------------------------+------------+-------------+
| "<"         | 리틀 엔디안              | 표준       | none        |
+-------------+--------------------------+------------+-------------+
| ">"         | 빅 엔디안                | 표준       | none        |
+-------------+--------------------------+------------+-------------+
| "!"         | 네트워크 (= 빅 엔디안)   | 표준       | none        |
+-------------+--------------------------+------------+-------------+

첫 번째 문자가 이들 중 하나가 아니면, "'@'"로 가정합니다.

네이티브 바이트 순서는 호스트 시스템에 따라 빅 엔디안이나 리틀 엔디안
입니다. 예를 들어, 인텔 x86과 AMD64 (x86-64)는 리틀 엔디안입니다; 모토
로라 68000과 PowerPC G5는 빅 엔디안입니다; ARM과 인텔 Itanium에는 전환
가능한 엔디안(bi-endian) 기능이 있습니다. 시스템의 엔디안을 확인하려면
"sys.byteorder"를 사용하십시오.

네이티브 크기와 정렬은 C 컴파일러의 "sizeof" 표현식을 사용하여 결정됩
니다. 이것은 항상 네이티브 바이트 순서와 결합합니다.

표준 크기는 포맷 문자에만 의존합니다; 포맷 문자 섹션의 표를 참조하십시
오.

"'@'"과 "'='"의 차이점에 유의하십시오; 둘 다 네이티브 바이트 순서를 사
용하지만, 후자는 크기와 정렬이 표준화됩니다.

"'!'" 형식은 IETF RFC 1700에 정의된 대로 항상 빅 엔디안인 네트워크 바
이트 순서를 나타냅니다.

네이티브가 아닌 바이트 순서(강제 바이트 스와핑)를 표시하는 방법은 없습
니다; "'<'"나 "'>'"를 적절히 선택하십시오.

노트:

1. 패딩은 연속되는 구조체 멤버 간에만 자동으로 추가됩니다. 인코딩된 구
   조체의 시작이나 끝에는 패딩이 추가되지 않습니다.

2. 네이티브가 아닌 크기와 정렬을 사용할 때는 패딩이 추가되지 않습니다,
   예를 들어 '<', '>', '=' 및 '!' 에서.

3. 구조체의 끝을 특정 형의 정렬 요구 사항에 맞추려면, 반복 횟수가 0인
   해당 형의 코드로 포맷을 끝내십시오. 예를 참조하십시오.


포맷 문자
---------

포맷 문자는 다음과 같은 의미가 있습니다; C와 파이썬 값 사이의 변환은
형을 주면 분명해야 합니다. '표준 크기' 열은 표준 크기를 사용할 때 패킹
된 값의 크기를 바이트 단위로 나타냅니다; 즉, 포맷 문자열이 "'<'",
"'>'", "'!'" 또는 "'='" 중 하나로 시작하는 경우입니다. 네이티브 크기를
사용할 때, 패킹 된 값의 크기는 플랫폼에 따라 다릅니다.

+----------+----------------------------+----------------------+------------------+--------------+
| 포맷     | C형                        | 파이썬 형            | 표준 크기        | 노트         |
|==========|============================|======================|==================|==============|
| "x"      | 패드 바이트                | 값이 없습니다        |                  |              |
+----------+----------------------------+----------------------+------------------+--------------+
| "c"      | "char"                     | 길이가 1인 bytes     | 1                |              |
+----------+----------------------------+----------------------+------------------+--------------+
| "b"      | "signed char"              | 정수                 | 1                | (1), (2)     |
+----------+----------------------------+----------------------+------------------+--------------+
| "B"      | "unsigned char"            | 정수                 | 1                | (2)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "?"      | "_Bool"                    | bool                 | 1                | (1)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "h"      | "short"                    | 정수                 | 2                | (2)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "H"      | "unsigned short"           | 정수                 | 2                | (2)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "i"      | "int"                      | 정수                 | 4                | (2)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "I"      | "unsigned int"             | 정수                 | 4                | (2)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "l"      | "long"                     | 정수                 | 4                | (2)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "L"      | "unsigned long"            | 정수                 | 4                | (2)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "q"      | "long long"                | 정수                 | 8                | (2)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "Q"      | "unsigned long long"       | 정수                 | 8                | (2)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "n"      | "ssize_t"                  | 정수                 |                  | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "N"      | "size_t"                   | 정수                 |                  | (3)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "e"      | (6)                        | float                | 2                | (4)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "f"      | "float"                    | float                | 4                | (4)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "d"      | "double"                   | float                | 8                | (4)          |
+----------+----------------------------+----------------------+------------------+--------------+
| "s"      | "char[]"                   | bytes                |                  |              |
+----------+----------------------------+----------------------+------------------+--------------+
| "p"      | "char[]"                   | bytes                |                  |              |
+----------+----------------------------+----------------------+------------------+--------------+
| "P"      | "void *"                   | 정수                 |                  | (5)          |
+----------+----------------------------+----------------------+------------------+--------------+

버전 3.3에서 변경: "'n'"과 "'N'" 포맷에 대한 지원이 추가되었습니다.

버전 3.6에서 변경: "'e'" 포맷에 대한 지원이 추가되었습니다.

노트:

1. "'?'" 변환 코드는 C99가 정의한 "_Bool" 형에 해당합니다. 이 형을 사
   용할 수 없으면, "char"를 사용하여 시뮬레이션 됩니다. 표준 모드에서
   는, 항상 1바이트로 표현됩니다.

2. 정수 변환 코드 중 하나를 사용하여 정수가 아닌 값을 패킹하려고 할 때
   , 정수가 아닌 값에 "__index__()" 메서드가 있으면 패킹 전에 해당 메
   서드가 호출되어 인자를 정수로 변환합니다.

   버전 3.2에서 변경: 정수가 아닌 값에서 "__index__()" 메서드를 사용하
   는 것을 추가했습니다.

3. "'n'"과 "'N'" 변환 코드는 (기본값이나 "'@'" 바이트 순서 문자로 선택
   된) 네이티브 크기에만 사용할 수 있습니다. 표준 크기의 경우, 응용 프
   로그램에 맞는 다른 정수 포맷을 사용할 수 있습니다.

4. "'f'", "'d'" 및 "'e'" 변환 코드의 경우, 패킹 된 표현은 플랫폼에서
   사용하는 부동 소수점 형식과 관계없이 IEEE 754 binary32, binary64 또
   는 binary16 형식을 사용합니다 (각각 "'f'", "'d'" 또는 "'e'").

5. "'P'" 포맷 문자는 (기본값이나 "'@'" 바이트 순서 문자로 선택된) 네이
   티브 바이트 순서에만 사용할 수 있습니다. 바이트 순서 문자 "'='"는
   호스트 시스템에 따라 리틀이나 빅 엔디안 순서를 사용하도록 선택합니
   다. struct 모듈은 이를 네이티브 순서로 해석하지 않아서, "'P'" 형식
   을 사용할 수 없습니다.

6. IEEE 754 binary16 "반 정밀도" 형은 2008년 IEEE 754 표준 개정판에서
   도입되었습니다. 부호 비트, 5비트 지수 및 11비트 정밀도(10비트가 명
   시적으로 저장됩니다)를 가지며, 전체 정밀도에서 대략 "6.1e-05"와
   "6.5e+04" 사이의 숫자를 나타낼 수 있습니다. 이 형은 C 컴파일러에서
   널리 지원되지 않습니다: 일반적인 기계에서는, unsigned short를 저장
   에 사용할 수 있지만, 수학 연산에는 사용할 수 없습니다. 자세한 내용
   은 half-precision floating-point format의 Wikipedia 페이지를 참조하
   십시오.

포맷 문자 앞에는 정수 반복 횟수가 올 수 있습니다. 예를 들어, 포맷 문자
열 "'4h'"는 "'hhhh'"와 정확히 같습니다.

포맷 사이의 공백 문자는 무시됩니다; 횟수와 형식 사이에는 공백이 없어야
합니다.

"'s'" 포맷 문자의 경우, 횟수는 다른 포맷 문자와 같은 반복 횟수가 아닌
바이트열의 길이로 해석됩니다; 예를 들어, "'10s'"는 단일 10바이트 문자
열을 의미하고, "'10c'"는 10문자를 의미합니다. 횟수를 지정하지 않으면,
기본값은 1입니다. 패킹의 경우, 맞도록 문자열이 잘리거나 널 바이트로 채
워집니다. 언 패킹의 경우, 결과 바이트열 객체는 항상 지정된 바이트 수를
갖습니다. 특별한 경우로, "'0s'"는 하나의 빈 문자열을 의미합니다(반면에
"'0c'"는 0문자를 의미합니다).

정수 형식 ("'b'", "'B'", "'h'", "'H'", "'i'", "'I'", "'l'", "'L'",
"'q'", "'Q'") 중 하나를 사용하여 값 "x"를 패킹할 때, "x"가 해당 포맷의
유효한 범위를 벗어나면 "struct.error"가 발생합니다.

버전 3.1에서 변경: 이전에는, 일부 정수 포맷은 범위를 벗어난 값을 래핑
하고 "struct.error" 대신 "DeprecationWarning"을 발생시켰습니다.

"'p'" 포맷 문자는 "파스칼 문자열"을 인코딩하는데, 이는 카운트에 의해
주어진 *고정된 바이트 수*에 저장된 짧은 가변 길이 문자열을 의미합니다.
저장된 첫 번째 바이트는 문자열의 길이나 255중 작은 값입니다. 문자열의
바이트가 그 뒤에 옵니다. "pack()"에 전달된 문자열이 너무 길면 (횟수 빼
기 1보다 길면), 문자열의 선행 "count-1" 바이트만 저장됩니다. 문자열이
"count-1"보다 짧으면, 전부 정확한 바이트 수가 되도록 널 바이트로 채워
집니다. "unpack()"의 경우, "'p'" 포맷 문자는 "count" 바이트를 소비하지
만, 반환된 문자열은 255바이트를 초과할 수 없음에 유의하십시오.

"'?'" 포맷 문자의 경우, 반환 값은 "True"나 "False"입니다. 패킹할 때,
인자 객체의 논리값이 사용됩니다. 네이티브나 표준 bool 표현에서 0이나 1
이 패킹 되고, 언 패킹할 때 모든 0이 아닌 값은 "True"가 됩니다.


예
--

참고:

  모든 예는 빅 엔디안 기계에서 네이티브 바이트 순서, 크기 및 정렬을 가
  정합니다.

3개의 정수를 패킹/언 패킹하는 기본 예제:

   >>> from struct import *
   >>> pack('hhl', 1, 2, 3)
   b'\x00\x01\x00\x02\x00\x00\x00\x03'
   >>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
   (1, 2, 3)
   >>> calcsize('hhl')
   8

언 패킹 된 필드는 변수에 대입하거나 결과를 네임드 튜플로 감싸서 이름을
붙일 수 있습니다:

   >>> record = b'raymond   \x32\x12\x08\x01\x08'
   >>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)

   >>> from collections import namedtuple
   >>> Student = namedtuple('Student', 'name serialnum school gradelevel')
   >>> Student._make(unpack('<10sHHb', record))
   Student(name=b'raymond   ', serialnum=4658, school=264, gradelevel=8)

정렬 요구 사항을 충족시키는 데 필요한 패딩이 다르기 때문에 포맷 문자의
순서는 크기에 영향을 줄 수 있습니다:

   >>> pack('ci', b'*', 0x12131415)
   b'*\x00\x00\x00\x12\x13\x14\x15'
   >>> pack('ic', 0x12131415, b'*')
   b'\x12\x13\x14\x15*'
   >>> calcsize('ci')
   8
   >>> calcsize('ic')
   5

다음 포맷 "'llh0l'"는 long이 4바이트 경계에 정렬된다고 가정할 때 끝에
2개의 패드 바이트를 지정합니다:

   >>> pack('llh0l', 1, 2, 3)
   b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

이것은 네이티브 크기와 정렬이 유효한 경우에만 작동합니다; 표준 크기와
정렬은 어떤 정렬도 강제하지 않습니다.

더 보기:

  모듈 "array"
     동종 데이터의 패킹 된 바이너리 저장소.

  모듈 "xdrlib"
     XDR 데이터의 패킹과 언 패킹.


클래스
======

"struct" 모듈은 또한 다음 형을 정의합니다:

class struct.Struct(format)

   포맷 문자열 *format*에 따라 바이너리 데이터를 쓰고 읽는 새 Struct
   객체를 반환합니다. Struct 객체를 한 번 만들고 메서드를 호출하는 것
   은 포맷 문자열을 한 번만 컴파일하면 되기 때문에 같은 포맷으로
   "struct" 함수를 호출하는 것보다 효율적입니다.

   참고:

     "Struct" 와 모듈 수준 함수에 전달된 최신 포맷 문자열의 컴파일된
     버전이 캐시 되므로, 몇 가지 포맷 문자열만 사용하는 프로그램은 단
     일 "Struct" 인스턴스 재사용에 대해 신경 쓸 필요가 없습니다.

   컴파일된 Struct 객체는 다음 메서드와 어트리뷰트를 지원합니다:

   pack(v1, v2, ...)

      "pack()" 함수와 동일하고, 컴파일된 포맷을 사용합니다.
      ("len(result)"는 "size"와 같게 됩니다.)

   pack_into(buffer, offset, v1, v2, ...)

      "pack_into()" 함수와 동일하고, 컴파일된 포맷을 사용합니다.

   unpack(buffer)

      "unpack()" 함수와 동일하고, 컴파일된 포맷을 사용합니다. 바이트
      단위의 버퍼 크기는 "size"와 같아야 합니다.

   unpack_from(buffer, offset=0)

      "unpack_from()" 함수와 동일하고, 컴파일된 포맷을 사용합니다.
      *offset* 위치에서 시작하는 바이트 단위의 버퍼 크기는 "size" 이상
      이어야 합니다.

   iter_unpack(buffer)

      "iter_unpack()" 함수와 동일하고, 컴파일된 포맷을 사용합니다. 바
      이트 단위의 버퍼 크기는 "size"의 배수이어야 합니다.

      버전 3.4에 추가.

   format

      이 Struct 객체를 구성하는 데 사용된 포맷 문자열.

      버전 3.7에서 변경: 포맷 문자열형은 이제 "bytes" 대신 "str"입니다
      .

   size

      "format"에 해당하는 구조체("pack()" 메서드에 의해 생성된 바이트
      열 객체)의 계산된 크기.
