move to new cspot

This commit is contained in:
philippe44
2023-03-25 16:48:41 -07:00
parent c712b78931
commit 008c36facf
2983 changed files with 465270 additions and 13569 deletions

View File

@@ -0,0 +1,6 @@
*.o*
*.bak
build/
codec/*.a
.vs/
*.user

View File

@@ -0,0 +1,241 @@
__________________________________________________________________________________________________________________________________
__________________________________________________________________________________________________________________________________
Apple Lossless Format "Magic Cookie" Description
__________________________________________________________________________________________________________________________________
__________________________________________________________________________________________________________________________________
Many encoded formats for audio require additional, codec specific configuration information in order to operate successfully.
This codec specific information is often called a 'magic cookie'. The Apple Lossless codec's 'magic cookie' contains the
ALACSpecificConfig and optional ALACChannelLayoutInfo (both described below).
The 'magic cookie' must accompany the bitstream when stored in any file container (M4A/MP4, CAF) so that it may be provided to the
decoder when decoding the bitstream. From the caller's perspective, the 'magic cookie' is opaque and should be stored in the file
and presented to the decoder exactly as it is vended from the encoder (and consequently stored in the file).
The ALAC 'magic cookie' as stored in a file has all fields described in big-endian order (regardless of file format).
The layout of the 'magic cookie' is as follows:
---------------- ALAC Specific Info (24 bytes) (mandatory) ---------------------------
(ALACSpecificConfig) Decoder Info
---------------- Channel Layout Info (24 bytes) (optional) ----------------------------
(ALAC Channel Layout Info) Channel Layout Info
If the channel layout is absent from the cookie, then the following assumptions are made:
1 channel - mono
2 channels - stereo in left, right order
> 2 channels - no specific channel designation or role.
__________________________________________________________________________________________________________________________________
* ALAC Specific Info (24 bytes) (mandatory)
__________________________________________________________________________________________________________________________________
The Apple Lossless codec stores specific information about the encoded stream in the ALACSpecificConfig. This
info is vended by the encoder and is used to setup the decoder for a given encoded bitstream.
When read from and written to a file, the fields of this struct must be in big-endian order.
When vended by the encoder (and received by the decoder) the struct values will be in big-endian order.
/*
struct ALACSpecificConfig (defined in ALACAudioTypes.h)
abstract This struct is used to describe codec provided information about the encoded Apple Lossless bitstream.
It must accompany the encoded stream in the containing audio file and be provided to the decoder.
field frameLength uint32_t indicating the frames per packet when no explicit frames per packet setting is
present in the packet header. The encoder frames per packet can be explicitly set
but for maximum compatibility, the default encoder setting of 4096 should be used.
field compatibleVersion uint8_t indicating compatible version,
value must be set to 0
field bitDepth uint8_t describes the bit depth of the source PCM data (maximum value = 32)
field pb uint8_t currently unused tuning parameter.
value should be set to 40
field mb uint8_t currently unused tuning parameter.
value should be set to 10
field kb uint8_t currently unused tuning parameter.
value should be set to 14
field numChannels uint8_t describes the channel count (1 = mono, 2 = stereo, etc...)
when channel layout info is not provided in the 'magic cookie', a channel count > 2
describes a set of discreet channels with no specific ordering
field maxRun uint16_t currently unused.
value should be set to 255
field maxFrameBytes uint32_t the maximum size of an Apple Lossless packet within the encoded stream.
value of 0 indicates unknown
field avgBitRate uint32_t the average bit rate in bits per second of the Apple Lossless stream.
value of 0 indicates unknown
field sampleRate uint32_t sample rate of the encoded stream
*/
typedef struct ALACSpecificConfig
{
uint32_t frameLength;
uint8_t compatibleVersion;
uint8_t bitDepth;
uint8_t pb;
uint8_t mb;
uint8_t kb;
uint8_t numChannels;
uint16_t maxRun;
uint32_t maxFrameBytes;
uint32_t avgBitRate;
uint32_t sampleRate;
} ALACSpecificConfig;
__________________________________________________________________________________________________________________________________
Channel Layout Info (24 bytes) (optional)
__________________________________________________________________________________________________________________________________
The Apple Lossless codec can support a specific set of channel layouts. When channel information is vended
by the encoder (in the 'magic cookie'), it is formatted in the the ALACChannelLayoutInfo.
When read from and written to a file, the fields of this struct must be in big-endian order.
When vended by the encoder (and received by the decoder) the struct values will be in big-endian order.
/*
struct ALACChannelLayoutInfo (defined in ALACAudioTypes.h)
abstract This struct is used to specify particular channel orderings or configurations.
It is an optional portion of the 'magic cookie', being required to describe specific channel layouts (see below)
of more than 2 channels.
field channelLayoutInfoSize uint32_t indicates the size of the channel layout data
value should be set to 24
field channelLayoutInfoID uint32_t identifier indicating that channel layout info is present
value = 'chan'
field versionFlags uint32_t version flags
value should be set to 0
field channelLayoutTag uint32_t channel layout type
from defined list in ALACAudioTypes.h (see below)
field reserved1 uint32_t currently unused field
value should be set to 0
field reserved2 uint32_t currently unused field
value should be set to 0
*/
typedef struct ALACChannelLayoutInfo
{
uint32_t channelLayoutInfoSize;
uint32_t channelLayoutInfoID;
uint32_t versionFlags;
uint32_t channelLayoutTag;
uint32_t reserved1;
uint32_t reserved2;
} ALACChannelLayoutInfo;
* Channel Layout Tags
These constants will be used to describe the bitstream's channel layout. (defined in ALACAudioTypes.h)
enum
{
kALACChannelLayoutTag_Mono = (100<<16) | 1, // C
kALACChannelLayoutTag_Stereo = (101<<16) | 2, // L R
kALACChannelLayoutTag_MPEG_3_0_B = (113<<16) | 3, // C L R
kALACChannelLayoutTag_MPEG_4_0_B = (116<<16) | 4, // C L R Cs
kALACChannelLayoutTag_MPEG_5_0_D = (120<<16) | 5, // C L R Ls Rs
kALACChannelLayoutTag_MPEG_5_1_D = (124<<16) | 6, // C L R Ls Rs LFE
kALACChannelLayoutTag_AAC_6_1 = (142<<16) | 7, // C L R Ls Rs Cs LFE
kALACChannelLayoutTag_MPEG_7_1_B = (127<<16) | 8 // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
};
__________________________________________________________________________________________________________________________________
__________________________________________________________________________________________________________________________________
* Storing Apple Lossless Magic Cookie in Audio Files
__________________________________________________________________________________________________________________________________
__________________________________________________________________________________________________________________________________
The Apple Lossless Magic Cookie is treated as opaque by file parsing code. The 'magic cookie' vended by the encoder
is placed without modification into the audio file and the read from that file and passed (unmodified) to the decoder.
__________________________________________________________________________________________________________________________________
* CAF File
In a CAF file (Core Audio File), the 'magic cookie' is stored in CAF's Magic Cookie chunk ('kuki').
__________________________________________________________________________________________________________________________________
* MP4/M4A File
In an MP4/M4A file, the 'magic cookie' is encapsulated in the AudioSample entry of a Sound Description box ('stsd').
An ISO style full box header to describe the ALACSpecificConfig portion is appended to the AudioSampleEntry, followed by the
'magic cookie' as it is vended by the encoder.
(All fields are stored in big-endian order: see ISO/IEC 14496-12 for a full description of the SoundDescription and AudioSampleEntry boxes, etc.)
---------------- SoundDescriptionBox (FullBox) ----------------------------
SampleEntrySize // = sizeof(SoundDescriptionBox)(16) + sizeof (AudioSampleEntry)(AudioSampleEntry.SampleEntrySize)
SampleEntryType // = 'stsd'
VersionFlags // = 0
EntryCount // = 1
---------------- Audio Sample Entry (REQUIRED) -----------------------------
SampleEntrySize // sizeof(AudioSampleEntry)(36) + sizeof(full ISO box header)(12) + sizeof(Apple Lossless Magic Cookie)
SampleEntryType // = 'alac', specifies that the AudioSampleEntry describes an Apple Lossless bitstream
mReserved[6] // = 0
dref index // = 1
reserved[2] // = 0
channel count // = number of channels as a uint_16 value
sample size // = source pcm bitdepth (example = 16bit source pcm)
predefined // = 0
reserved // = 0
sample rate // sample rate as a uint_32 value
Appended to AudioSampleEntry:
ALAC Specific Info Size // uint_32 value, = 36 (12 + sizeof(ALACSpecificConfig))
ALAC Specific Info ID // uint_32 value, = 'alac', format ID which matches the Audio Sample Entry SampleEntryType field
Version Flags // uint_32 value, = 0
Apple Lossless Magic Cookie // 'magic cookie' vended from ALAC encoder (24 or 48 Bytes)
__________________________________________________________________________________________________________________________________
__________________________________________________________________________________________________________________________________
* Compatibility
__________________________________________________________________________________________________________________________________
__________________________________________________________________________________________________________________________________
Previous versions of the Apple Lossless encoder vended a different 'magic cookie'. To ensure compatibility, the Apple Lossless decoder
must be prepared to parse a 'magic cookie' in the format described below. Note that the 'magic cookie' defined above is
encapsulated in the following method and can be extracted as a contiguous set of bytes.
---------------- Format Atom (12 bytes) --------------------------------
(uint_32) Format Atom Size // = 12
(uint_32) Channel Layout Info ID // = 'frma'
(uint_32) Format Type // = 'alac'
---------------- ALAC Specific Info (36 bytes) (required) --------------
(uint_32) ALAC Specific Info Size // = 36 (12 + sizeof(ALACSpecificConfig))
(uint_32) ALAC Specific Info ID // = 'alac', format ID which matches the Audio Sample Entry SampleEntryType field
(uint_32) Version Flags // = 0
[ Apple Lossless Magic Cookie (see above) ]
---------------- Terminator Atom (8 bytes) -----------------------------
(uint_32) Channel Layout Info Size // = 8
(uint_32) Channel Layout Info ID // = 0

View File

@@ -0,0 +1,9 @@
By submitting a request, you represent that you have the right to license
your contribution to the community, and agree that your contributions are
licensed under the [Apache License Version 2.0](LICENSE).
For existing files modified by your request, you represent that you have
retained any existing copyright notices and licensing terms. For each new
file in your request, you represent that you have added to the file a
copyright notice (including the year and the copyright owner's name) and
ALAC's licensing terms.

View File

@@ -0,0 +1,53 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.

View File

@@ -0,0 +1,9 @@
By submitting a request, you represent that you have the right to license
your contribution to the community, and agree that your contributions are
licensed under the [Apache License Version 2.0](LICENSE).
For existing files modified by your request, you represent that you have
retained any existing copyright notices and licensing terms. For each new
file in your request, you represent that you have added to the file a
copyright notice (including the year and the copyright owner's name) and
ALAC's licensing terms.

View File

@@ -0,0 +1,44 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The Apple Lossless Format
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Apple Lossless supports the following features. Not all of these are implemented in alacconvert, though they are in the codec code provided.
1. Bit depths 16, 20, 24 and 32 bits.
2. Any arbitrary integer sample rate from 1 to 384,000 Hz. In theory rates up to 4,294,967,295 (2^32 - 1) Hz could be supported.
3. From one to eight channels are supported. Channel orders for the supported formats are described as:
Num Chan Order
1 mono
2 stereo (Left, Right)
3 MPEG 3.0 B (Center, Left, Right)
4 MPEG 4.0 B (Center, Left, Right, Center Surround)
5 MPEG 5.0 D (Center, Left, Right, Left Surround, Right Surround)
6 MPEG 5.1 D (Center, Left, Right, Left Surround, Right Surround, Low Frequency Effects)
7 Apple AAC 6.1 (Center, Left, Right, Left Surround, Right Surround, Center Surround, Low Frequency Effects)
8 MPEG 7.1 B (Center, Left Center, Right Center, Left, Right, Left Surround, Right Surround, Low Frequency Effects)
4. Packet size defaults to 4096 sample frames of audio per packet. Other packet sizes are certainly possible. However, non-default packet sizes are not guaranteed to work properly on all hardware devices that support Apple Lossless. Packets above 16,384 sample frames are not supported.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
This package contains the sources for the Apple Lossless (ALAC) encoder and decoder.
The "codec" directory contains all the sources necessary for a functioning codec. Also includes is a makefile that will build libalac.a on a UNIX/Linux machine.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ALACconvert
The convert-utility directory contains sources to build alacconvert which is a simple utility that demonstrates how to use the included ALAC encoder and decoder.
alacconvert supports the following formats:
1. 16- or 24-bit mono or stereo .wav files where the data is little endian integer. Extended WAVE format chunks are not handled.
2. 16- or 24-bit mono or stereo .caf (Core Audio Format) files as well as certain multi-channel configurations where the data is big or little endian integer. It does no channel order manipulation.
3. ALAC .caf files.
Three project are provided to build a command line utility called alacconvert that converts cpm data to ALAC or vice versa. A Mac OS X Xcode project, A Windows Visual Studio project, and a generic UNIX/Linux make file.
Note: When building on Windows, if you are using a version of Visual Studio before Visual Studio 2010, <stdint.h> is not installed. You will need to acquire this file on your own. It can be put in the same directory as the project.

View File

@@ -0,0 +1,202 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: ALACAudioTypes.h
*/
#ifndef ALACAUDIOTYPES_H
#define ALACAUDIOTYPES_H
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
#include <stdint.h>
#if defined(__ppc__)
#define TARGET_RT_BIG_ENDIAN 1
#elif defined(__ppc64__)
#define TARGET_RT_BIG_ENDIAN 1
#endif
#define kChannelAtomSize 12
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmultichar"
enum
{
kALAC_UnimplementedError = -4,
kALAC_FileNotFoundError = -43,
kALAC_ParamError = -50,
kALAC_MemFullError = -108
};
enum
{
kALACFormatAppleLossless = 'alac',
kALACFormatLinearPCM = 'lpcm'
};
enum
{
kALACMaxChannels = 8,
kALACMaxEscapeHeaderBytes = 8,
kALACMaxSearches = 16,
kALACMaxCoefs = 16,
kALACDefaultFramesPerPacket = 4096
};
typedef uint32_t ALACChannelLayoutTag;
enum
{
kALACFormatFlagIsFloat = (1 << 0), // 0x1
kALACFormatFlagIsBigEndian = (1 << 1), // 0x2
kALACFormatFlagIsSignedInteger = (1 << 2), // 0x4
kALACFormatFlagIsPacked = (1 << 3), // 0x8
kALACFormatFlagIsAlignedHigh = (1 << 4), // 0x10
};
enum
{
#if TARGET_RT_BIG_ENDIAN
kALACFormatFlagsNativeEndian = kALACFormatFlagIsBigEndian
#else
kALACFormatFlagsNativeEndian = 0
#endif
};
// this is required to be an IEEE 64bit float
typedef double alac_float64_t;
// These are the Channel Layout Tags used in the Channel Layout Info portion of the ALAC magic cookie
enum
{
kALACChannelLayoutTag_Mono = (100<<16) | 1, // C
kALACChannelLayoutTag_Stereo = (101<<16) | 2, // L R
kALACChannelLayoutTag_MPEG_3_0_B = (113<<16) | 3, // C L R
kALACChannelLayoutTag_MPEG_4_0_B = (116<<16) | 4, // C L R Cs
kALACChannelLayoutTag_MPEG_5_0_D = (120<<16) | 5, // C L R Ls Rs
kALACChannelLayoutTag_MPEG_5_1_D = (124<<16) | 6, // C L R Ls Rs LFE
kALACChannelLayoutTag_AAC_6_1 = (142<<16) | 7, // C L R Ls Rs Cs LFE
kALACChannelLayoutTag_MPEG_7_1_B = (127<<16) | 8 // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
};
// ALAC currently only utilizes these channels layouts. There is a one for one correspondance between a
// given number of channels and one of these layout tags
static const ALACChannelLayoutTag ALACChannelLayoutTags[kALACMaxChannels] =
{
kALACChannelLayoutTag_Mono, // C
kALACChannelLayoutTag_Stereo, // L R
kALACChannelLayoutTag_MPEG_3_0_B, // C L R
kALACChannelLayoutTag_MPEG_4_0_B, // C L R Cs
kALACChannelLayoutTag_MPEG_5_0_D, // C L R Ls Rs
kALACChannelLayoutTag_MPEG_5_1_D, // C L R Ls Rs LFE
kALACChannelLayoutTag_AAC_6_1, // C L R Ls Rs Cs LFE
kALACChannelLayoutTag_MPEG_7_1_B // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
};
// AudioChannelLayout from CoreAudioTypes.h. We never need the AudioChannelDescription so we remove it
struct ALACAudioChannelLayout
{
ALACChannelLayoutTag mChannelLayoutTag;
uint32_t mChannelBitmap;
uint32_t mNumberChannelDescriptions;
};
typedef struct ALACAudioChannelLayout ALACAudioChannelLayout;
struct AudioFormatDescription
{
alac_float64_t mSampleRate;
uint32_t mFormatID;
uint32_t mFormatFlags;
uint32_t mBytesPerPacket;
uint32_t mFramesPerPacket;
uint32_t mBytesPerFrame;
uint32_t mChannelsPerFrame;
uint32_t mBitsPerChannel;
uint32_t mReserved;
};
typedef struct AudioFormatDescription AudioFormatDescription;
/* Lossless Definitions */
enum
{
kALACCodecFormat = 'alac',
kALACVersion = 0,
kALACCompatibleVersion = kALACVersion,
kALACDefaultFrameSize = 4096
};
// note: this struct is wrapped in an 'alac' atom in the sample description extension area
// note: in QT movies, it will be further wrapped in a 'wave' atom surrounded by 'frma' and 'term' atoms
typedef struct ALACSpecificConfig
{
uint32_t frameLength;
uint8_t compatibleVersion;
uint8_t bitDepth; // max 32
uint8_t pb; // 0 <= pb <= 255
uint8_t mb;
uint8_t kb;
uint8_t numChannels;
uint16_t maxRun;
uint32_t maxFrameBytes;
uint32_t avgBitRate;
uint32_t sampleRate;
} ALACSpecificConfig;
// The AudioChannelLayout atom type is not exposed yet so define it here
enum
{
AudioChannelLayoutAID = 'chan'
};
#pragma GCC diagnostic pop
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef __cplusplus
}
#endif
#endif /* ALACAUDIOTYPES_H */

View File

@@ -0,0 +1,260 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*=============================================================================
File: ALACBitUtilities.c
$NoKeywords: $
=============================================================================*/
#include <stdio.h>
#include "ALACBitUtilities.h"
// BitBufferInit
//
void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
{
bits->cur = buffer;
bits->end = bits->cur + byteSize;
bits->bitIndex = 0;
bits->byteSize = byteSize;
}
// BitBufferRead
//
uint32_t BitBufferRead( BitBuffer * bits, uint8_t numBits )
{
uint32_t returnBits;
//Assert( numBits <= 16 );
returnBits = ((uint32_t)bits->cur[0] << 16) | ((uint32_t)bits->cur[1] << 8) | ((uint32_t)bits->cur[2]);
returnBits = returnBits << bits->bitIndex;
returnBits &= 0x00FFFFFF;
bits->bitIndex += numBits;
returnBits = returnBits >> (24 - numBits);
bits->cur += (bits->bitIndex >> 3);
bits->bitIndex &= 7;
//Assert( bits->cur <= bits->end );
return returnBits;
}
// BitBufferReadSmall
//
// Reads up to 8 bits
uint8_t BitBufferReadSmall( BitBuffer * bits, uint8_t numBits )
{
uint16_t returnBits;
//Assert( numBits <= 8 );
returnBits = (bits->cur[0] << 8) | bits->cur[1];
returnBits = returnBits << bits->bitIndex;
bits->bitIndex += numBits;
returnBits = returnBits >> (16 - numBits);
bits->cur += (bits->bitIndex >> 3);
bits->bitIndex &= 7;
//Assert( bits->cur <= bits->end );
return (uint8_t)returnBits;
}
// BitBufferReadOne
//
// Reads one byte
uint8_t BitBufferReadOne( BitBuffer * bits )
{
uint8_t returnBits;
returnBits = (bits->cur[0] >> (7 - bits->bitIndex)) & 1;
bits->bitIndex++;
bits->cur += (bits->bitIndex >> 3);
bits->bitIndex &= 7;
//Assert( bits->cur <= bits->end );
return returnBits;
}
// BitBufferPeek
//
uint32_t BitBufferPeek( BitBuffer * bits, uint8_t numBits )
{
return ((((((uint32_t) bits->cur[0] << 16) | ((uint32_t) bits->cur[1] << 8) |
((uint32_t) bits->cur[2])) << bits->bitIndex) & 0x00FFFFFF) >> (24 - numBits));
}
// BitBufferPeekOne
//
uint32_t BitBufferPeekOne( BitBuffer * bits )
{
return ((bits->cur[0] >> (7 - bits->bitIndex)) & 1);
}
// BitBufferUnpackBERSize
//
uint32_t BitBufferUnpackBERSize( BitBuffer * bits )
{
uint32_t size;
uint8_t tmp;
for ( size = 0, tmp = 0x80u; tmp &= 0x80u; size = (size << 7u) | (tmp & 0x7fu) )
tmp = (uint8_t) BitBufferReadSmall( bits, 8 );
return size;
}
// BitBufferGetPosition
//
uint32_t BitBufferGetPosition( BitBuffer * bits )
{
uint8_t * begin;
begin = bits->end - bits->byteSize;
return ((uint32_t)(bits->cur - begin) * 8) + bits->bitIndex;
}
// BitBufferByteAlign
//
void BitBufferByteAlign( BitBuffer * bits, int32_t addZeros )
{
// align bit buffer to next byte boundary, writing zeros if requested
if ( bits->bitIndex == 0 )
return;
if ( addZeros )
BitBufferWrite( bits, 0, 8 - bits->bitIndex );
else
BitBufferAdvance( bits, 8 - bits->bitIndex );
}
// BitBufferAdvance
//
void BitBufferAdvance( BitBuffer * bits, uint32_t numBits )
{
if ( numBits )
{
bits->bitIndex += numBits;
bits->cur += (bits->bitIndex >> 3);
bits->bitIndex &= 7;
}
}
// BitBufferRewind
//
void BitBufferRewind( BitBuffer * bits, uint32_t numBits )
{
uint32_t numBytes;
if ( numBits == 0 )
return;
if ( bits->bitIndex >= numBits )
{
bits->bitIndex -= numBits;
return;
}
numBits -= bits->bitIndex;
bits->bitIndex = 0;
numBytes = numBits / 8;
numBits = numBits % 8;
bits->cur -= numBytes;
if ( numBits > 0 )
{
bits->bitIndex = 8 - numBits;
bits->cur--;
}
if ( bits->cur < (bits->end - bits->byteSize) )
{
//DebugCMsg("BitBufferRewind: Rewound too far.");
bits->cur = (bits->end - bits->byteSize);
bits->bitIndex = 0;
}
}
// BitBufferWrite
//
void BitBufferWrite( BitBuffer * bits, uint32_t bitValues, uint32_t numBits )
{
uint32_t invBitIndex;
RequireAction( bits != nil, return; );
RequireActionSilent( numBits > 0, return; );
invBitIndex = 8 - bits->bitIndex;
while ( numBits > 0 )
{
uint32_t tmp;
uint8_t shift;
uint8_t mask;
uint32_t curNum;
curNum = MIN( invBitIndex, numBits );
tmp = bitValues >> (numBits - curNum);
shift = (uint8_t)(invBitIndex - curNum);
mask = 0xffu >> (8 - curNum); // must be done in two steps to avoid compiler sequencing ambiguity
mask <<= shift;
bits->cur[0] = (bits->cur[0] & ~mask) | (((uint8_t) tmp << shift) & mask);
numBits -= curNum;
// increment to next byte if need be
invBitIndex -= curNum;
if ( invBitIndex == 0 )
{
invBitIndex = 8;
bits->cur++;
}
}
bits->bitIndex = 8 - invBitIndex;
}
void BitBufferReset( BitBuffer * bits )
//void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize )
{
bits->cur = bits->end - bits->byteSize;
bits->bitIndex = 0;
}
#if PRAGMA_MARK
#pragma mark -
#endif

View File

@@ -0,0 +1,104 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*=============================================================================
File: ALACBitUtilities.h
$NoKeywords: $
=============================================================================*/
#ifndef __ALACBITUTILITIES_H
#define __ALACBITUTILITIES_H
#include <stdint.h>
#ifndef MIN
#define MIN(x, y) ( (x)<(y) ?(x) :(y) )
#endif //MIN
#ifndef MAX
#define MAX(x, y) ( (x)>(y) ?(x): (y) )
#endif //MAX
#ifndef nil
#define nil NULL
#endif
#define RequireAction(condition, action) if (!(condition)) { action }
#define RequireActionSilent(condition, action) if (!(condition)) { action }
#define RequireNoErr(condition, action) if ((condition)) { action }
#ifdef __cplusplus
extern "C" {
#endif
enum
{
ALAC_noErr = 0
};
typedef enum
{
ID_SCE = 0, /* Single Channel Element */
ID_CPE = 1, /* Channel Pair Element */
ID_CCE = 2, /* Coupling Channel Element */
ID_LFE = 3, /* LFE Channel Element */
ID_DSE = 4, /* not yet supported */
ID_PCE = 5,
ID_FIL = 6,
ID_END = 7
} ELEMENT_TYPE;
// types
typedef struct BitBuffer
{
uint8_t * cur;
uint8_t * end;
uint32_t bitIndex;
uint32_t byteSize;
} BitBuffer;
/*
BitBuffer routines
- these routines take a fixed size buffer and read/write to it
- bounds checking must be done by the client
*/
void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize );
uint32_t BitBufferRead( BitBuffer * bits, uint8_t numBits ); // note: cannot read more than 16 bits at a time
uint8_t BitBufferReadSmall( BitBuffer * bits, uint8_t numBits );
uint8_t BitBufferReadOne( BitBuffer * bits );
uint32_t BitBufferPeek( BitBuffer * bits, uint8_t numBits ); // note: cannot read more than 16 bits at a time
uint32_t BitBufferPeekOne( BitBuffer * bits );
uint32_t BitBufferUnpackBERSize( BitBuffer * bits );
uint32_t BitBufferGetPosition( BitBuffer * bits );
void BitBufferByteAlign( BitBuffer * bits, int32_t addZeros );
void BitBufferAdvance( BitBuffer * bits, uint32_t numBits );
void BitBufferRewind( BitBuffer * bits, uint32_t numBits );
void BitBufferWrite( BitBuffer * bits, uint32_t value, uint32_t numBits );
void BitBufferReset( BitBuffer * bits);
#ifdef __cplusplus
}
#endif
#endif /* __BITUTILITIES_H */

View File

@@ -0,0 +1,737 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: ALACDecoder.cpp
*/
#include <stdlib.h>
#include <string.h>
#include "ALACDecoder.h"
#include "dplib.h"
#include "aglib.h"
#include "matrixlib.h"
#include "ALACBitUtilities.h"
#include "EndianPortable.h"
#if (__GNUC__) > 4 || defined (__APPLE__)
#pragma GCC diagnostic ignored "-Wunused-const-variable"
#endif
#if !defined(__APPLE__)
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#endif
// constants/data
const uint32_t kMaxBitDepth = 32; // max allowed bit depth is 32
// prototypes
static void Zero16( int16_t * buffer, uint32_t numItems, uint32_t stride );
static void Zero24( uint8_t * buffer, uint32_t numItems, uint32_t stride );
static void Zero32( int32_t * buffer, uint32_t numItems, uint32_t stride );
/*
Constructor
*/
ALACDecoder::ALACDecoder() :
mMixBufferU( nil ),
mMixBufferV( nil ),
mPredictor( nil ),
mShiftBuffer( nil )
{
memset( &mConfig, 0, sizeof(mConfig) );
}
/*
Destructor
*/
ALACDecoder::~ALACDecoder()
{
// delete the matrix mixing buffers
if ( mMixBufferU )
{
free(mMixBufferU);
mMixBufferU = NULL;
}
if ( mMixBufferV )
{
free(mMixBufferV);
mMixBufferV = NULL;
}
// delete the dynamic predictor's "corrector" buffer
// - note: mShiftBuffer shares memory with this buffer
if ( mPredictor )
{
free(mPredictor);
mPredictor = NULL;
}
}
/*
Init()
- initialize the decoder with the given configuration
*/
int32_t ALACDecoder::Init( void * inMagicCookie, uint32_t inMagicCookieSize )
{
int32_t status = ALAC_noErr;
ALACSpecificConfig theConfig;
uint8_t * theActualCookie = (uint8_t *)inMagicCookie;
uint32_t theCookieBytesRemaining = inMagicCookieSize;
// For historical reasons the decoder needs to be resilient to magic cookies vended by older encoders.
// As specified in the ALACMagicCookieDescription.txt document, there may be additional data encapsulating
// the ALACSpecificConfig. This would consist of format ('frma') and 'alac' atoms which precede the
// ALACSpecificConfig.
// See ALACMagicCookieDescription.txt for additional documentation concerning the 'magic cookie'
// skip format ('frma') atom if present
if (theActualCookie[4] == 'f' && theActualCookie[5] == 'r' && theActualCookie[6] == 'm' && theActualCookie[7] == 'a')
{
theActualCookie += 12;
theCookieBytesRemaining -= 12;
}
// skip 'alac' atom header if present
if (theActualCookie[4] == 'a' && theActualCookie[5] == 'l' && theActualCookie[6] == 'a' && theActualCookie[7] == 'c')
{
theActualCookie += 12;
theCookieBytesRemaining -= 12;
}
// read the ALACSpecificConfig
if (theCookieBytesRemaining >= sizeof(ALACSpecificConfig))
{
theConfig.frameLength = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->frameLength);
theConfig.compatibleVersion = ((ALACSpecificConfig *)theActualCookie)->compatibleVersion;
theConfig.bitDepth = ((ALACSpecificConfig *)theActualCookie)->bitDepth;
theConfig.pb = ((ALACSpecificConfig *)theActualCookie)->pb;
theConfig.mb = ((ALACSpecificConfig *)theActualCookie)->mb;
theConfig.kb = ((ALACSpecificConfig *)theActualCookie)->kb;
theConfig.numChannels = ((ALACSpecificConfig *)theActualCookie)->numChannels;
theConfig.maxRun = Swap16BtoN(((ALACSpecificConfig *)theActualCookie)->maxRun);
theConfig.maxFrameBytes = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->maxFrameBytes);
theConfig.avgBitRate = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->avgBitRate);
theConfig.sampleRate = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->sampleRate);
mConfig = theConfig;
RequireAction( mConfig.compatibleVersion <= kALACVersion, return kALAC_ParamError; );
// allocate mix buffers
mMixBufferU = (int32_t *) calloc( mConfig.frameLength * sizeof(int32_t), 1 );
mMixBufferV = (int32_t *) calloc( mConfig.frameLength * sizeof(int32_t), 1 );
// allocate dynamic predictor buffer
mPredictor = (int32_t *) calloc( mConfig.frameLength * sizeof(int32_t), 1 );
// "shift off" buffer shares memory with predictor buffer
mShiftBuffer = (uint16_t *) mPredictor;
RequireAction( (mMixBufferU != nil) && (mMixBufferV != nil) && (mPredictor != nil),
status = kALAC_MemFullError; goto Exit; );
}
else
{
status = kALAC_ParamError;
}
// skip to Channel Layout Info
// theActualCookie += sizeof(ALACSpecificConfig);
// Currently, the Channel Layout Info portion of the magic cookie (as defined in the
// ALACMagicCookieDescription.txt document) is unused by the decoder.
Exit:
return status;
}
/*
Decode()
- the decoded samples are interleaved into the output buffer in the order they arrive in
the bitstream
*/
int32_t ALACDecoder::Decode( BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples )
{
BitBuffer shiftBits;
uint32_t bits1, bits2;
uint8_t tag;
uint8_t elementInstanceTag;
AGParamRec agParams;
uint32_t channelIndex;
int16_t coefsU[32]; // max possible size is 32 although NUMCOEPAIRS is the current limit
int16_t coefsV[32];
uint8_t numU, numV;
uint8_t mixBits;
int8_t mixRes;
uint16_t unusedHeader;
uint8_t escapeFlag;
uint32_t chanBits;
uint8_t bytesShifted;
uint32_t shift;
uint8_t modeU, modeV;
uint32_t denShiftU, denShiftV;
uint16_t pbFactorU, pbFactorV;
uint16_t pb;
int16_t * samples;
int16_t * out16;
uint8_t * out20;
uint8_t * out24;
int32_t * out32;
uint8_t headerByte;
uint8_t partialFrame;
uint32_t extraBits;
int32_t val;
uint32_t i, j;
int32_t status;
RequireAction( (bits != nil) && (sampleBuffer != nil) && (outNumSamples != nil), return kALAC_ParamError; );
RequireAction( numChannels > 0, return kALAC_ParamError; );
mActiveElements = 0;
channelIndex = 0;
samples = (int16_t *) sampleBuffer;
status = ALAC_noErr;
*outNumSamples = numSamples;
while ( status == ALAC_noErr )
{
// bail if we ran off the end of the buffer
RequireAction( bits->cur < bits->end, status = kALAC_ParamError; goto Exit; );
// copy global decode params for this element
pb = mConfig.pb;
// read element tag
tag = BitBufferReadSmall( bits, 3 );
switch ( tag )
{
case ID_SCE:
case ID_LFE:
{
// mono/LFE channel
elementInstanceTag = BitBufferReadSmall( bits, 4 );
mActiveElements |= (1u << elementInstanceTag);
// read the 12 unused header bits
unusedHeader = (uint16_t) BitBufferRead( bits, 12 );
RequireAction( unusedHeader == 0, status = kALAC_ParamError; goto Exit; );
// read the 1-bit "partial frame" flag, 2-bit "shift-off" flag & 1-bit "escape" flag
headerByte = (uint8_t) BitBufferRead( bits, 4 );
partialFrame = headerByte >> 3;
bytesShifted = (headerByte >> 1) & 0x3u;
RequireAction( bytesShifted != 3, status = kALAC_ParamError; goto Exit; );
shift = bytesShifted * 8;
escapeFlag = headerByte & 0x1;
chanBits = mConfig.bitDepth - (bytesShifted * 8);
// check for partial frame to override requested numSamples
if ( partialFrame != 0 )
{
numSamples = BitBufferRead( bits, 16 ) << 16;
numSamples |= BitBufferRead( bits, 16 );
}
if ( escapeFlag == 0 )
{
// compressed frame, read rest of parameters
mixBits = (uint8_t) BitBufferRead( bits, 8 );
mixRes = (int8_t) BitBufferRead( bits, 8 );
//Assert( (mixBits == 0) && (mixRes == 0) ); // no mixing for mono
headerByte = (uint8_t) BitBufferRead( bits, 8 );
modeU = headerByte >> 4;
denShiftU = headerByte & 0xfu;
headerByte = (uint8_t) BitBufferRead( bits, 8 );
pbFactorU = headerByte >> 5;
numU = headerByte & 0x1fu;
for ( i = 0; i < numU; i++ )
coefsU[i] = (int16_t) BitBufferRead( bits, 16 );
// if shift active, skip the the shift buffer but remember where it starts
if ( bytesShifted != 0 )
{
shiftBits = *bits;
BitBufferAdvance( bits, (bytesShifted * 8) * numSamples );
}
// decompress
set_ag_params( &agParams, mConfig.mb, (pb * pbFactorU) / 4, mConfig.kb, numSamples, numSamples, mConfig.maxRun );
status = dyn_decomp( &agParams, bits, mPredictor, numSamples, chanBits, &bits1 );
RequireNoErr( status, goto Exit; );
if ( modeU == 0 )
{
unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
}
else
{
// the special "numActive == 31" mode can be done in-place
unpc_block( mPredictor, mPredictor, numSamples, nil, 31, chanBits, 0 );
unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
}
}
else
{
//Assert( bytesShifted == 0 );
// uncompressed frame, copy data into the mix buffer to use common output code
shift = 32 - chanBits;
if ( chanBits <= 16 )
{
for ( i = 0; i < numSamples; i++ )
{
val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits );
val = (val << shift) >> shift;
mMixBufferU[i] = val;
}
}
else
{
// BitBufferRead() can't read more than 16 bits at a time so break up the reads
extraBits = chanBits - 16;
for ( i = 0; i < numSamples; i++ )
{
val = (int32_t) BitBufferRead( bits, 16 );
val = (val << 16) >> shift;
mMixBufferU[i] = val | BitBufferRead( bits, (uint8_t) extraBits );
}
}
mixBits = mixRes = 0;
bits1 = chanBits * numSamples;
bytesShifted = 0;
}
// now read the shifted values into the shift buffer
if ( bytesShifted != 0 )
{
shift = bytesShifted * 8;
//Assert( shift <= 16 );
for ( i = 0; i < numSamples; i++ )
mShiftBuffer[i] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
}
// convert 32-bit integers into output buffer
switch ( mConfig.bitDepth )
{
case 16:
out16 = &((int16_t *)sampleBuffer)[channelIndex];
for ( i = 0, j = 0; i < numSamples; i++, j += numChannels )
out16[j] = (int16_t) mMixBufferU[i];
break;
case 20:
out20 = (uint8_t *)sampleBuffer + (channelIndex * 3);
copyPredictorTo20( mMixBufferU, out20, numChannels, numSamples );
break;
case 24:
out24 = (uint8_t *)sampleBuffer + (channelIndex * 3);
if ( bytesShifted != 0 )
copyPredictorTo24Shift( mMixBufferU, mShiftBuffer, out24, numChannels, numSamples, bytesShifted );
else
copyPredictorTo24( mMixBufferU, out24, numChannels, numSamples );
break;
case 32:
out32 = &((int32_t *)sampleBuffer)[channelIndex];
if ( bytesShifted != 0 )
copyPredictorTo32Shift( mMixBufferU, mShiftBuffer, out32, numChannels, numSamples, bytesShifted );
else
copyPredictorTo32( mMixBufferU, out32, numChannels, numSamples);
break;
}
channelIndex += 1;
*outNumSamples = numSamples;
break;
}
case ID_CPE:
{
// if decoding this pair would take us over the max channels limit, bail
if ( (channelIndex + 2) > numChannels )
goto NoMoreChannels;
// stereo channel pair
elementInstanceTag = BitBufferReadSmall( bits, 4 );
mActiveElements |= (1u << elementInstanceTag);
// read the 12 unused header bits
unusedHeader = (uint16_t) BitBufferRead( bits, 12 );
RequireAction( unusedHeader == 0, status = kALAC_ParamError; goto Exit; );
// read the 1-bit "partial frame" flag, 2-bit "shift-off" flag & 1-bit "escape" flag
headerByte = (uint8_t) BitBufferRead( bits, 4 );
partialFrame = headerByte >> 3;
bytesShifted = (headerByte >> 1) & 0x3u;
RequireAction( bytesShifted != 3, status = kALAC_ParamError; goto Exit; );
shift = bytesShifted * 8;
escapeFlag = headerByte & 0x1;
chanBits = mConfig.bitDepth - (bytesShifted * 8) + 1;
// check for partial frame length to override requested numSamples
if ( partialFrame != 0 )
{
numSamples = BitBufferRead( bits, 16 ) << 16;
numSamples |= BitBufferRead( bits, 16 );
}
if ( escapeFlag == 0 )
{
// compressed frame, read rest of parameters
mixBits = (uint8_t) BitBufferRead( bits, 8 );
mixRes = (int8_t) BitBufferRead( bits, 8 );
headerByte = (uint8_t) BitBufferRead( bits, 8 );
modeU = headerByte >> 4;
denShiftU = headerByte & 0xfu;
headerByte = (uint8_t) BitBufferRead( bits, 8 );
pbFactorU = headerByte >> 5;
numU = headerByte & 0x1fu;
for ( i = 0; i < numU; i++ )
coefsU[i] = (int16_t) BitBufferRead( bits, 16 );
headerByte = (uint8_t) BitBufferRead( bits, 8 );
modeV = headerByte >> 4;
denShiftV = headerByte & 0xfu;
headerByte = (uint8_t) BitBufferRead( bits, 8 );
pbFactorV = headerByte >> 5;
numV = headerByte & 0x1fu;
for ( i = 0; i < numV; i++ )
coefsV[i] = (int16_t) BitBufferRead( bits, 16 );
// if shift active, skip the interleaved shifted values but remember where they start
if ( bytesShifted != 0 )
{
shiftBits = *bits;
BitBufferAdvance( bits, (bytesShifted * 8) * 2 * numSamples );
}
// decompress and run predictor for "left" channel
set_ag_params( &agParams, mConfig.mb, (pb * pbFactorU) / 4, mConfig.kb, numSamples, numSamples, mConfig.maxRun );
status = dyn_decomp( &agParams, bits, mPredictor, numSamples, chanBits, &bits1 );
RequireNoErr( status, goto Exit; );
if ( modeU == 0 )
{
unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
}
else
{
// the special "numActive == 31" mode can be done in-place
unpc_block( mPredictor, mPredictor, numSamples, nil, 31, chanBits, 0 );
unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
}
// decompress and run predictor for "right" channel
set_ag_params( &agParams, mConfig.mb, (pb * pbFactorV) / 4, mConfig.kb, numSamples, numSamples, mConfig.maxRun );
status = dyn_decomp( &agParams, bits, mPredictor, numSamples, chanBits, &bits2 );
RequireNoErr( status, goto Exit; );
if ( modeV == 0 )
{
unpc_block( mPredictor, mMixBufferV, numSamples, &coefsV[0], numV, chanBits, denShiftV );
}
else
{
// the special "numActive == 31" mode can be done in-place
unpc_block( mPredictor, mPredictor, numSamples, nil, 31, chanBits, 0 );
unpc_block( mPredictor, mMixBufferV, numSamples, &coefsV[0], numV, chanBits, denShiftV );
}
}
else
{
//Assert( bytesShifted == 0 );
// uncompressed frame, copy data into the mix buffers to use common output code
chanBits = mConfig.bitDepth;
shift = 32 - chanBits;
if ( chanBits <= 16 )
{
for ( i = 0; i < numSamples; i++ )
{
val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits );
val = (val << shift) >> shift;
mMixBufferU[i] = val;
val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits );
val = (val << shift) >> shift;
mMixBufferV[i] = val;
}
}
else
{
// BitBufferRead() can't read more than 16 bits at a time so break up the reads
extraBits = chanBits - 16;
for ( i = 0; i < numSamples; i++ )
{
val = (int32_t) BitBufferRead( bits, 16 );
val = (val << 16) >> shift;
mMixBufferU[i] = val | BitBufferRead( bits, (uint8_t)extraBits );
val = (int32_t) BitBufferRead( bits, 16 );
val = (val << 16) >> shift;
mMixBufferV[i] = val | BitBufferRead( bits, (uint8_t)extraBits );
}
}
bits1 = chanBits * numSamples;
bits2 = chanBits * numSamples;
mixBits = mixRes = 0;
bytesShifted = 0;
}
// now read the shifted values into the shift buffer
if ( bytesShifted != 0 )
{
shift = bytesShifted * 8;
//Assert( shift <= 16 );
for ( i = 0; i < (numSamples * 2); i += 2 )
{
mShiftBuffer[i + 0] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
mShiftBuffer[i + 1] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
}
}
// un-mix the data and convert to output format
// - note that mixRes = 0 means just interleave so we use that path for uncompressed frames
switch ( mConfig.bitDepth )
{
case 16:
out16 = &((int16_t *)sampleBuffer)[channelIndex];
unmix16( mMixBufferU, mMixBufferV, out16, numChannels, numSamples, mixBits, mixRes );
break;
case 20:
out20 = (uint8_t *)sampleBuffer + (channelIndex * 3);
unmix20( mMixBufferU, mMixBufferV, out20, numChannels, numSamples, mixBits, mixRes );
break;
case 24:
out24 = (uint8_t *)sampleBuffer + (channelIndex * 3);
unmix24( mMixBufferU, mMixBufferV, out24, numChannels, numSamples,
mixBits, mixRes, mShiftBuffer, bytesShifted );
break;
case 32:
out32 = &((int32_t *)sampleBuffer)[channelIndex];
unmix32( mMixBufferU, mMixBufferV, out32, numChannels, numSamples,
mixBits, mixRes, mShiftBuffer, bytesShifted );
break;
}
channelIndex += 2;
*outNumSamples = numSamples;
break;
}
case ID_CCE:
case ID_PCE:
{
// unsupported element, bail
//AssertNoErr( tag );
status = kALAC_ParamError;
break;
}
case ID_DSE:
{
// data stream element -- parse but ignore
status = this->DataStreamElement( bits );
break;
}
case ID_FIL:
{
// fill element -- parse but ignore
status = this->FillElement( bits );
break;
}
case ID_END:
{
// frame end, all done so byte align the frame and check for overruns
BitBufferByteAlign( bits, false );
//Assert( bits->cur == bits->end );
goto Exit;
}
}
#if ! DEBUG
// if we've decoded all of our channels, bail (but not in debug b/c we want to know if we're seeing bad bits)
// - this also protects us if the config does not match the bitstream or crap data bits follow the audio bits
if ( channelIndex >= numChannels )
break;
#endif
}
NoMoreChannels:
// if we get here and haven't decoded all of the requested channels, fill the remaining channels with zeros
for ( ; channelIndex < numChannels; channelIndex++ )
{
switch ( mConfig.bitDepth )
{
case 16:
{
int16_t * fill16 = &((int16_t *)sampleBuffer)[channelIndex];
Zero16( fill16, numSamples, numChannels );
break;
}
case 24:
{
uint8_t * fill24 = (uint8_t *)sampleBuffer + (channelIndex * 3);
Zero24( fill24, numSamples, numChannels );
break;
}
case 32:
{
int32_t * fill32 = &((int32_t *)sampleBuffer)[channelIndex];
Zero32( fill32, numSamples, numChannels );
break;
}
}
}
Exit:
return status;
}
#if PRAGMA_MARK
#pragma mark -
#endif
/*
FillElement()
- they're just filler so we don't need 'em
*/
int32_t ALACDecoder::FillElement( BitBuffer * bits )
{
int16_t count;
// 4-bit count or (4-bit + 8-bit count) if 4-bit count == 15
// - plus this weird -1 thing I still don't fully understand
count = BitBufferReadSmall( bits, 4 );
if ( count == 15 )
count += (int16_t) BitBufferReadSmall( bits, 8 ) - 1;
BitBufferAdvance( bits, count * 8 );
RequireAction( bits->cur <= bits->end, return kALAC_ParamError; );
return ALAC_noErr;
}
/*
DataStreamElement()
- we don't care about data stream elements so just skip them
*/
int32_t ALACDecoder::DataStreamElement( BitBuffer * bits )
{
uint8_t element_instance_tag;
int32_t data_byte_align_flag;
uint16_t count;
// the tag associates this data stream element with a given audio element
element_instance_tag = BitBufferReadSmall( bits, 4 );
data_byte_align_flag = BitBufferReadOne( bits );
// 8-bit count or (8-bit + 8-bit count) if 8-bit count == 255
count = BitBufferReadSmall( bits, 8 );
if ( count == 255 )
count += BitBufferReadSmall( bits, 8 );
// the align flag means the bitstream should be byte-aligned before reading the following data bytes
if ( data_byte_align_flag )
BitBufferByteAlign( bits, false );
// skip the data bytes
BitBufferAdvance( bits, count * 8 );
RequireAction( bits->cur <= bits->end, return kALAC_ParamError; );
return ALAC_noErr;
}
/*
ZeroN()
- helper routines to clear out output channel buffers when decoding fewer channels than requested
*/
static void Zero16( int16_t * buffer, uint32_t numItems, uint32_t stride )
{
if ( stride == 1 )
{
memset( buffer, 0, numItems * sizeof(int16_t) );
}
else
{
for ( uint32_t index = 0; index < (numItems * stride); index += stride )
buffer[index] = 0;
}
}
static void Zero24( uint8_t * buffer, uint32_t numItems, uint32_t stride )
{
if ( stride == 1 )
{
memset( buffer, 0, numItems * 3 );
}
else
{
for ( uint32_t index = 0; index < (numItems * stride * 3); index += (stride * 3) )
{
buffer[index + 0] = 0;
buffer[index + 1] = 0;
buffer[index + 2] = 0;
}
}
}
static void Zero32( int32_t * buffer, uint32_t numItems, uint32_t stride )
{
if ( stride == 1 )
{
memset( buffer, 0, numItems * sizeof(int32_t) );
}
else
{
for ( uint32_t index = 0; index < (numItems * stride); index += stride )
buffer[index] = 0;
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: ALACDecoder.h
*/
#ifndef _ALACDECODER_H
#define _ALACDECODER_H
#if PRAGMA_ONCE
#pragma once
#endif
#include <stdint.h>
#include "ALACAudioTypes.h"
struct BitBuffer;
class ALACDecoder
{
public:
ALACDecoder();
~ALACDecoder();
int32_t Init( void * inMagicCookie, uint32_t inMagicCookieSize );
int32_t Decode( struct BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples );
public:
// decoding parameters (public for use in the analyzer)
ALACSpecificConfig mConfig;
protected:
int32_t FillElement( struct BitBuffer * bits );
int32_t DataStreamElement( struct BitBuffer * bits );
uint16_t mActiveElements;
// decoding buffers
int32_t * mMixBufferU;
int32_t * mMixBufferV;
int32_t * mPredictor;
uint16_t * mShiftBuffer; // note: this points to mPredictor's memory but different
// variable for clarity and type difference
};
#endif /* _ALACDECODER_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: ALACEncoder.h
*/
#pragma once
#include <stdint.h>
#include "ALACAudioTypes.h"
struct BitBuffer;
class ALACEncoder
{
public:
ALACEncoder();
virtual ~ALACEncoder();
virtual int32_t Encode(AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat,
unsigned char * theReadBuffer, unsigned char * theWriteBuffer, int32_t * ioNumBytes);
virtual int32_t Finish( );
void SetFastMode( bool fast ) { mFastMode = fast; };
// this must be called *before* InitializeEncoder()
void SetFrameSize( uint32_t frameSize ) { mFrameSize = frameSize; };
void GetConfig( ALACSpecificConfig & config );
uint32_t GetMagicCookieSize(uint32_t inNumChannels);
void GetMagicCookie( void * config, uint32_t * ioSize );
virtual int32_t InitializeEncoder(AudioFormatDescription theOutputFormat);
protected:
virtual void GetSourceFormat( const AudioFormatDescription * source, AudioFormatDescription * output );
int32_t EncodeStereo( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
int32_t EncodeStereoFast( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
int32_t EncodeStereoEscape( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t numSamples );
int32_t EncodeMono( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
// ALAC encoder parameters
int16_t mBitDepth;
bool mFastMode;
// encoding state
int16_t mLastMixRes[kALACMaxChannels];
// encoding buffers
int32_t * mMixBufferU;
int32_t * mMixBufferV;
int32_t * mPredictorU;
int32_t * mPredictorV;
uint16_t * mShiftBufferUV;
uint8_t * mWorkBuffer;
// per-channel coefficients buffers
int16_t mCoefsU[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
int16_t mCoefsV[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
// encoding statistics
uint32_t mTotalBytesGenerated;
uint32_t mAvgBitRate;
uint32_t mMaxFrameBytes;
uint32_t mFrameSize;
uint32_t mMaxOutputBytes;
uint32_t mNumChannels;
uint32_t mOutputSampleRate;
};

View File

@@ -0,0 +1,335 @@
APPLE PUBLIC SOURCE LICENSE
Version 2.0 - August 6, 2003
Please read this License carefully before downloading this software. By
downloading or using this software, you are agreeing to be bound by the terms
of this License. If you do not or cannot agree to the terms of this License,
please do not download or use the software.
Apple Note: In January 2007, Apple changed its corporate name from "Apple
Computer, Inc." to "Apple Inc." This change has been reflected below and
copyright years updated, but no other changes have been made to the APSL 2.0.
1. General; Definitions. This License applies to any program or other
work which Apple Inc. ("Apple") makes publicly available and which contains a
notice placed by Apple identifying such program or work as "Original Code" and
stating that it is subject to the terms of this Apple Public Source License
version 2.0 ("License"). As used in this License:
1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is the
grantor of rights, (i) claims of patents that are now or hereafter acquired,
owned by or assigned to Apple and (ii) that cover subject matter contained in
the Original Code, but only to the extent necessary to use, reproduce and/or
distribute the Original Code without infringement; and (b) in the case where
You are the grantor of rights, (i) claims of patents that are now or hereafter
acquired, owned by or assigned to You and (ii) that cover subject matter in
Your Modifications, taken alone or in combination with Original Code.
1.2 "Contributor" means any person or entity that creates or contributes to
the creation of Modifications.
1.3 "Covered Code" means the Original Code, Modifications, the combination
of Original Code and any Modifications, and/or any respective portions thereof.
1.4 "Externally Deploy" means: (a) to sublicense, distribute or otherwise
make Covered Code available, directly or indirectly, to anyone other than You;
and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way
to provide a service, including but not limited to delivery of content, through
electronic communication with a client other than You.
1.5 "Larger Work" means a work which combines Covered Code or portions
thereof with code not governed by the terms of this License.
1.6 "Modifications" mean any addition to, deletion from, and/or change to,
the substance and/or structure of the Original Code, any previous
Modifications, the combination of Original Code and any previous Modifications,
and/or any respective portions thereof. When code is released as a series of
files, a Modification is: (a) any addition to or deletion from the contents of
a file containing Covered Code; and/or (b) any new file or other representation
of computer program statements that contains any part of Covered Code.
1.7 "Original Code" means (a) the Source Code of a program or other work as
originally made available by Apple under this License, including the Source
Code of any updates or upgrades to such programs or works made available by
Apple under this License, and that has been expressly identified by Apple as
such in the header file(s) of such work; and (b) the object code compiled from
such Source Code and originally made available by Apple under this License
1.8 "Source Code" means the human readable form of a program or other work
that is suitable for making modifications to it, including all modules it
contains, plus any associated interface definition files, scripts used to
control compilation and installation of an executable (object code).
1.9 "You" or "Your" means an individual or a legal entity exercising rights
under this License. For legal entities, "You" or "Your" includes any entity
which controls, is controlled by, or is under common control with, You, where
"control" means (a) the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or (b) ownership
of fifty percent (50%) or more of the outstanding shares or beneficial
ownership of such entity.
2. Permitted Uses; Conditions & Restrictions. Subject to the terms and
conditions of this License, Apple hereby grants You, effective on the date You
accept this License and download the Original Code, a world-wide, royalty-free,
non-exclusive license, to the extent of Apple's Applicable Patent Rights and
copyrights covering the Original Code, to do the following:
2.1 Unmodified Code. You may use, reproduce, display, perform, internally
distribute within Your organization, and Externally Deploy verbatim, unmodified
copies of the Original Code, for commercial or non-commercial purposes,
provided that in each instance:
(a) You must retain and reproduce in all copies of Original Code the
copyright and other proprietary notices and disclaimers of Apple as they appear
in the Original Code, and keep intact all notices in the Original Code that
refer to this License; and
(b) You must include a copy of this License with every copy of Source Code
of Covered Code and documentation You distribute or Externally Deploy, and You
may not offer or impose any terms on such Source Code that alter or restrict
this License or the recipients' rights hereunder, except as permitted under
Section 6.
2.2 Modified Code. You may modify Covered Code and use, reproduce,
display, perform, internally distribute within Your organization, and
Externally Deploy Your Modifications and Covered Code, for commercial or
non-commercial purposes, provided that in each instance You also meet all of
these conditions:
(a) You must satisfy all the conditions of Section 2.1 with respect to the
Source Code of the Covered Code;
(b) You must duplicate, to the extent it does not already exist, the notice
in Exhibit A in each file of the Source Code of all Your Modifications, and
cause the modified files to carry prominent notices stating that You changed
the files and the date of any change; and
(c) If You Externally Deploy Your Modifications, You must make Source Code
of all Your Externally Deployed Modifications either available to those to whom
You have Externally Deployed Your Modifications, or publicly available. Source
Code of Your Externally Deployed Modifications must be released under the terms
set forth in this License, including the license grants set forth in Section 3
below, for as long as you Externally Deploy the Covered Code or twelve (12)
months from the date of initial External Deployment, whichever is longer. You
should preferably distribute the Source Code of Your Externally Deployed
Modifications electronically (e.g. download from a web site).
2.3 Distribution of Executable Versions. In addition, if You Externally
Deploy Covered Code (Original Code and/or Modifications) in object code,
executable form only, You must include a prominent notice, in the code itself
as well as in related documentation, stating that Source Code of the Covered
Code is available under the terms of this License with information on how and
where to obtain such Source Code.
2.4 Third Party Rights. You expressly acknowledge and agree that although
Apple and each Contributor grants the licenses to their respective portions of
the Covered Code set forth herein, no assurances are provided by Apple or any
Contributor that the Covered Code does not infringe the patent or other
intellectual property rights of any other entity. Apple and each Contributor
disclaim any liability to You for claims brought by any other entity based on
infringement of intellectual property rights or otherwise. As a condition to
exercising the rights and licenses granted hereunder, You hereby assume sole
responsibility to secure any other intellectual property rights needed, if any.
For example, if a third party patent license is required to allow You to
distribute the Covered Code, it is Your responsibility to acquire that license
before distributing the Covered Code.
3. Your Grants. In consideration of, and as a condition to, the licenses
granted to You under this License, You hereby grant to any person or entity
receiving or distributing Covered Code under this License a non-exclusive,
royalty-free, perpetual, irrevocable license, under Your Applicable Patent
Rights and other intellectual property rights (other than patent) owned or
controlled by You, to use, reproduce, display, perform, modify, sublicense,
distribute and Externally Deploy Your Modifications of the same scope and
extent as Apple's licenses under Sections 2.1 and 2.2 above.
4. Larger Works. You may create a Larger Work by combining Covered Code
with other code not governed by the terms of this License and distribute the
Larger Work as a single product. In each such instance, You must make sure the
requirements of this License are fulfilled for the Covered Code or any portion
thereof.
5. Limitations on Patent License. Except as expressly stated in Section
2, no other patent rights, express or implied, are granted by Apple herein.
Modifications and/or Larger Works may require additional patent licenses from
Apple which Apple may grant in its sole discretion.
6. Additional Terms. You may choose to offer, and to charge a fee for,
warranty, support, indemnity or liability obligations and/or other rights
consistent with the scope of the license granted herein ("Additional Terms") to
one or more recipients of Covered Code. However, You may do so only on Your own
behalf and as Your sole responsibility, and not on behalf of Apple or any
Contributor. You must obtain the recipient's agreement that any such Additional
Terms are offered by You alone, and You hereby agree to indemnify, defend and
hold Apple and every Contributor harmless for any liability incurred by or
claims asserted against Apple or such Contributor by reason of any such
Additional Terms.
7. Versions of the License. Apple may publish revised and/or new versions
of this License from time to time. Each version will be given a distinguishing
version number. Once Original Code has been published under a particular
version of this License, You may continue to use it under the terms of that
version. You may also choose to use such Original Code under the terms of any
subsequent version of this License published by Apple. No one other than Apple
has the right to modify the terms applicable to Covered Code created under this
License.
8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
part pre-release, untested, or not fully tested works. The Covered Code may
contain errors that could cause failures or loss of data, and may be incomplete
or contain inaccuracies. You expressly acknowledge and agree that use of the
Covered Code, or any portion thereof, is at Your sole and entire risk. THE
COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF
ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE"
FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF
SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF
QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. APPLE AND EACH
CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE
COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR
REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO ORAL OR
WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED
REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You acknowledge
that the Covered Code is not intended for use in the operation of nuclear
facilities, aircraft navigation, communication systems, or air traffic control
machines in which case the failure of the Covered Code could lead to death,
personal injury, or severe physical or environmental damage.
9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR
YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER
UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS
LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF
THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL
PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF
LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT
APPLY TO YOU. In no event shall Apple's total liability to You for all damages
(other than as may be required by applicable law) under this License exceed the
amount of fifty dollars ($50.00).
10. Trademarks. This License does not grant any rights to use the
trademarks or trade names "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime
Streaming Server" or any other trademarks, service marks, logos or trade names
belonging to Apple (collectively "Apple Marks") or to any trademark, service
mark, logo or trade name belonging to any Contributor. You agree not to use
any Apple Marks in or as part of the name of products derived from the Original
Code or to endorse or promote products derived from the Original Code other
than as expressly permitted by and in strict compliance at all times with
Apple's third party trademark usage guidelines which are posted at
http://www.apple.com/legal/guidelinesfor3rdparties.html.
11. Ownership. Subject to the licenses granted under this License, each
Contributor retains all rights, title and interest in and to any Modifications
made by such Contributor. Apple retains all rights, title and interest in and
to the Original Code and any Modifications made by or on behalf of Apple
("Apple Modifications"), and such Apple Modifications will not be automatically
subject to this License. Apple may, at its sole discretion, choose to license
such Apple Modifications under this License, or on different terms from those
contained in this License or may choose not to license them at all.
12. Termination.
12.1 Termination. This License and the rights granted hereunder will
terminate:
(a) automatically without notice from Apple if You fail to comply with any
term(s) of this License and fail to cure such breach within 30 days of becoming
aware of such breach;
(b) immediately in the event of the circumstances described in Section
13.5(b); or
(c) automatically without notice from Apple if You, at any time during the
term of this License, commence an action for patent infringement against Apple;
provided that Apple did not first commence an action for patent infringement
against You in that instance.
12.2 Effect of Termination. Upon termination, You agree to immediately stop
any further use, reproduction, modification, sublicensing and distribution of
the Covered Code. All sublicenses to the Covered Code which have been properly
granted prior to termination shall survive any termination of this License.
Provisions which, by their nature, should remain in effect beyond the
termination of this License shall survive, including but not limited to
Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable to any other
for compensation, indemnity or damages of any sort solely as a result of
terminating this License in accordance with its terms, and termination of this
License will be without prejudice to any other right or remedy of any party.
13. Miscellaneous.
13.1 Government End Users. The Covered Code is a "commercial item" as
defined in FAR 2.101. Government software and technical data rights in the
Covered Code include only those rights customarily provided to the public as
defined in this License. This customary commercial license in technical data
and software is provided in accordance with FAR 12.211 (Technical Data) and
12.212 (Computer Software) and, for Department of Defense purchases, DFAR
252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in
Commercial Computer Software or Computer Software Documentation). Accordingly,
all U.S. Government End Users acquire Covered Code with only those rights set
forth herein.
13.2 Relationship of Parties. This License will not be construed as
creating an agency, partnership, joint venture or any other form of legal
association between or among You, Apple or any Contributor, and You will not
represent to the contrary, whether expressly, by implication, appearance or
otherwise.
13.3 Independent Development. Nothing in this License will impair Apple's
right to acquire, license, develop, have others develop for it, market and/or
distribute technology or products that perform the same or similar functions
as, or otherwise compete with, Modifications, Larger Works, technology or
products that You may develop, produce, market or distribute.
13.4 Waiver; Construction. Failure by Apple or any Contributor to enforce
any provision of this License will not be deemed a waiver of future enforcement
of that or any other provision. Any law or regulation which provides that the
language of a contract shall be construed against the drafter will not apply to
this License.
13.5 Severability. (a) If for any reason a court of competent jurisdiction
finds any provision of this License, or portion thereof, to be unenforceable,
that provision of the License will be enforced to the maximum extent
permissible so as to effect the economic benefits and intent of the parties,
and the remainder of this License will continue in full force and effect. (b)
Notwithstanding the foregoing, if applicable law prohibits or restricts You
from fully and/or specifically complying with Sections 2 and/or 3 or prevents
the enforceability of either of those Sections, this License will immediately
terminate and You must immediately discontinue any use of the Covered Code and
destroy all copies of it that are in your possession or control.
13.6 Dispute Resolution. Any litigation or other dispute resolution between
You and Apple relating to this License shall take place in the Northern
District of California, and You and Apple hereby consent to the personal
jurisdiction of, and venue in, the state and federal courts within that
District with respect to this License. The application of the United Nations
Convention on Contracts for the International Sale of Goods is expressly
excluded.
13.7 Entire Agreement; Governing Law. This License constitutes the entire
agreement between the parties with respect to the subject matter hereof. This
License shall be governed by the laws of the United States and the State of
California, except that body of California law concerning conflicts of law.
Where You are located in the province of Quebec, Canada, the following clause
applies: The parties hereby confirm that they have requested that this License
and all related documents be drafted in English. Les parties ont exigé que le
présent contrat et tous les documents connexes soient rédigés en anglais.
EXHIBIT A.
"Portions Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
This file contains Original Code and/or Modifications of Original Code as
defined in and that are subject to the Apple Public Source License Version 2.0
(the 'License'). You may not use this file except in compliance with the
License. Please obtain a copy of the License at
http://www.opensource.apple.com/apsl/ and read it before using this file.
The Original Code and all software distributed under the License are
distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
specific language governing rights and limitations under the License."

View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
//
// EndianPortable.c
//
// Copyright 2011 Apple Inc. All rights reserved.
//
#include <stdio.h>
#include "EndianPortable.h"
#define BSWAP16(x) (((x << 8) | ((x >> 8) & 0x00ff)))
#define BSWAP32(x) (((x << 24) | ((x << 8) & 0x00ff0000) | ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff)))
#define BSWAP64(x) ((((int64_t)x << 56) | (((int64_t)x << 40) & 0x00ff000000000000LL) | \
(((int64_t)x << 24) & 0x0000ff0000000000LL) | (((int64_t)x << 8) & 0x000000ff00000000LL) | \
(((int64_t)x >> 8) & 0x00000000ff000000LL) | (((int64_t)x >> 24) & 0x0000000000ff0000LL) | \
(((int64_t)x >> 40) & 0x000000000000ff00LL) | (((int64_t)x >> 56) & 0x00000000000000ffLL)))
#if defined(__i386__)
#define TARGET_RT_LITTLE_ENDIAN 1
#elif defined(__x86_64__)
#define TARGET_RT_LITTLE_ENDIAN 1
#elif defined (TARGET_OS_WIN32)
#define TARGET_RT_LITTLE_ENDIAN 1
#elif defined (__arm__) || defined(__aarch64__)
#define TARGET_RT_LITTLE_ENDIAN 1
#endif
uint16_t Swap16NtoB(uint16_t inUInt16)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP16(inUInt16);
#else
return inUInt16;
#endif
}
uint16_t Swap16BtoN(uint16_t inUInt16)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP16(inUInt16);
#else
return inUInt16;
#endif
}
uint32_t Swap32NtoB(uint32_t inUInt32)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP32(inUInt32);
#else
return inUInt32;
#endif
}
uint32_t Swap32BtoN(uint32_t inUInt32)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP32(inUInt32);
#else
return inUInt32;
#endif
}
uint64_t Swap64BtoN(uint64_t inUInt64)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP64(inUInt64);
#else
return inUInt64;
#endif
}
uint64_t Swap64NtoB(uint64_t inUInt64)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP64(inUInt64);
#else
return inUInt64;
#endif
}
float SwapFloat32BtoN(float in)
{
#if TARGET_RT_LITTLE_ENDIAN
union {
float f;
int32_t i;
} x;
x.f = in;
x.i = BSWAP32(x.i);
return x.f;
#else
return in;
#endif
}
float SwapFloat32NtoB(float in)
{
#if TARGET_RT_LITTLE_ENDIAN
union {
float f;
int32_t i;
} x;
x.f = in;
x.i = BSWAP32(x.i);
return x.f;
#else
return in;
#endif
}
double SwapFloat64BtoN(double in)
{
#if TARGET_RT_LITTLE_ENDIAN
union {
double f;
int64_t i;
} x;
x.f = in;
x.i = BSWAP64(x.i);
return x.f;
#else
return in;
#endif
}
double SwapFloat64NtoB(double in)
{
#if TARGET_RT_LITTLE_ENDIAN
union {
double f;
int64_t i;
} x;
x.f = in;
x.i = BSWAP64(x.i);
return x.f;
#else
return in;
#endif
}
void Swap16(uint16_t * inUInt16)
{
*inUInt16 = BSWAP16(*inUInt16);
}
void Swap24(uint8_t * inUInt24)
{
uint8_t tempVal = inUInt24[0];
inUInt24[0] = inUInt24[2];
inUInt24[2] = tempVal;
}
void Swap32(uint32_t * inUInt32)
{
*inUInt32 = BSWAP32(*inUInt32);
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
//
// EndianPortable.h
//
// Copyright 2011 Apple Inc. All rights reserved.
//
#ifndef _EndianPortable_h
#define _EndianPortable_h
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
uint16_t Swap16NtoB(uint16_t inUInt16);
uint16_t Swap16BtoN(uint16_t inUInt16);
uint32_t Swap32NtoB(uint32_t inUInt32);
uint32_t Swap32BtoN(uint32_t inUInt32);
uint64_t Swap64BtoN(uint64_t inUInt64);
uint64_t Swap64NtoB(uint64_t inUInt64);
float SwapFloat32BtoN(float in);
float SwapFloat32NtoB(float in);
double SwapFloat64BtoN(double in);
double SwapFloat64NtoB(double in);
void Swap16(uint16_t * inUInt16);
void Swap24(uint8_t * inUInt24);
void Swap32(uint32_t * inUInt32);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,362 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: ag_dec.c
Contains: Adaptive Golomb decode routines.
Copyright: (c) 2001-2011 Apple, Inc.
*/
#include "aglib.h"
#include "ALACBitUtilities.h"
#include "ALACAudioTypes.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if __GNUC__ && TARGET_OS_MAC
#if __POWERPC__
#include <ppc_intrinsics.h>
#else
#include <libkern/OSByteOrder.h>
#endif
#endif
#define CODE_TO_LONG_MAXBITS 32
#define N_MAX_MEAN_CLAMP 0xffff
#define N_MEAN_CLAMP_VAL 0xffff
#define REPORT_VAL 40
#if __GNUC__
#define ALWAYS_INLINE __attribute__((always_inline))
#else
#define ALWAYS_INLINE
#endif
/* And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this
to help the compiler out. In many cases this required manual inlining or a macro. Sorry
if it is ugly but the performance gains are well worth it.
- WSK 5/19/04
*/
void set_standard_ag_params(AGParamRecPtr params, uint32_t fullwidth, uint32_t sectorwidth)
{
/* Use
fullwidth = sectorwidth = numOfSamples, for analog 1-dimensional type-short data,
but use
fullwidth = full image width, sectorwidth = sector (patch) width
for such as image (2-dim.) data.
*/
set_ag_params( params, MB0, PB0, KB0, fullwidth, sectorwidth, MAX_RUN_DEFAULT );
}
void set_ag_params(AGParamRecPtr params, uint32_t m, uint32_t p, uint32_t k, uint32_t f, uint32_t s, uint32_t maxrun)
{
params->mb = params->mb0 = m;
params->pb = p;
params->kb = k;
params->wb = (1u<<params->kb)-1;
params->qb = QB-params->pb;
params->fw = f;
params->sw = s;
params->maxrun = maxrun;
}
#if PRAGMA_MARK
#pragma mark -
#endif
// note: implementing this with some kind of "count leading zeros" assembly is a big performance win
static inline int32_t lead( int32_t m )
{
long j;
unsigned long c = (1ul << 31);
for(j=0; j < 32; j++)
{
if((c & m) != 0)
break;
c >>= 1;
}
return (j);
}
#define arithmin(a, b) ((a) < (b) ? (a) : (b))
static inline int32_t ALWAYS_INLINE lg3a( int32_t x)
{
int32_t result;
x += 3;
result = lead(x);
return 31 - result;
}
static inline uint32_t ALWAYS_INLINE read32bit( uint8_t * buffer )
{
// embedded CPUs typically can't read unaligned 32-bit words so just read the bytes
uint32_t value;
value = ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) |
((uint32_t)buffer[2] << 8) | (uint32_t)buffer[3];
return value;
}
#if PRAGMA_MARK
#pragma mark -
#endif
#define get_next_fromlong(inlong, suff) ((inlong) >> (32 - (suff)))
static inline uint32_t ALWAYS_INLINE
getstreambits( uint8_t *in, int32_t bitoffset, int32_t numbits )
{
uint32_t load1, load2;
uint32_t byteoffset = bitoffset / 8;
uint32_t result;
//Assert( numbits <= 32 );
load1 = read32bit( in + byteoffset );
if ( (numbits + (bitoffset & 0x7)) > 32)
{
int32_t load2shift;
result = load1 << (bitoffset & 0x7);
load2 = (uint32_t) in[byteoffset+4];
load2shift = (8-(numbits + (bitoffset & 0x7)-32));
load2 >>= load2shift;
result >>= (32-numbits);
result |= load2;
}
else
{
result = load1 >> (32-numbits-(bitoffset & 7));
}
// a shift of >= "the number of bits in the type of the value being shifted" results in undefined
// behavior so don't try to shift by 32
if ( numbits != (sizeof(result) * 8) )
result &= ~(0xfffffffful << numbits);
return result;
}
static inline int32_t dyn_get(unsigned char *in, uint32_t *bitPos, uint32_t m, uint32_t k)
{
uint32_t tempbits = *bitPos;
uint32_t result;
uint32_t pre = 0, v;
uint32_t streamlong;
streamlong = read32bit( in + (tempbits >> 3) );
streamlong <<= (tempbits & 7);
/* find the number of bits in the prefix */
{
uint32_t notI = ~streamlong;
pre = lead( notI);
}
if(pre >= MAX_PREFIX_16)
{
pre = MAX_PREFIX_16;
tempbits += pre;
streamlong <<= pre;
result = get_next_fromlong(streamlong,MAX_DATATYPE_BITS_16);
tempbits += MAX_DATATYPE_BITS_16;
}
else
{
// all of the bits must fit within the long we have loaded
//Assert(pre+1+k <= 32);
tempbits += pre;
tempbits += 1;
streamlong <<= pre+1;
v = get_next_fromlong(streamlong, k);
tempbits += k;
result = pre*m + v-1;
if(v<2) {
result -= (v-1);
tempbits -= 1;
}
}
*bitPos = tempbits;
return result;
}
static inline int32_t dyn_get_32bit( uint8_t * in, uint32_t * bitPos, int32_t m, int32_t k, int32_t maxbits )
{
uint32_t tempbits = *bitPos;
uint32_t v;
uint32_t streamlong;
uint32_t result;
streamlong = read32bit( in + (tempbits >> 3) );
streamlong <<= (tempbits & 7);
/* find the number of bits in the prefix */
{
uint32_t notI = ~streamlong;
result = lead( notI);
}
if(result >= MAX_PREFIX_32)
{
result = getstreambits(in, tempbits+MAX_PREFIX_32, maxbits);
tempbits += MAX_PREFIX_32 + maxbits;
}
else
{
/* all of the bits must fit within the long we have loaded*/
//Assert(k<=14);
//Assert(result<MAX_PREFIX_32);
//Assert(result+1+k <= 32);
tempbits += result;
tempbits += 1;
if (k != 1)
{
streamlong <<= result+1;
v = get_next_fromlong(streamlong, k);
tempbits += k;
tempbits -= 1;
result = result*m;
if(v>=2)
{
result += (v-1);
tempbits += 1;
}
}
}
*bitPos = tempbits;
return result;
}
int32_t dyn_decomp( AGParamRecPtr params, BitBuffer * bitstream, int32_t * pc, int32_t numSamples, int32_t maxSize, uint32_t * outNumBits )
{
uint8_t *in;
int32_t *outPtr = pc;
uint32_t bitPos, startPos, maxPos;
uint32_t j, m, k, n, c, mz;
int32_t del, zmode;
uint32_t mb;
uint32_t pb_local = params->pb;
uint32_t kb_local = params->kb;
uint32_t wb_local = params->wb;
int32_t status;
RequireAction( (bitstream != nil) && (pc != nil) && (outNumBits != nil), return kALAC_ParamError; );
*outNumBits = 0;
in = bitstream->cur;
startPos = bitstream->bitIndex;
maxPos = bitstream->byteSize * 8;
bitPos = startPos;
mb = params->mb0;
zmode = 0;
c = 0;
status = ALAC_noErr;
while (c < numSamples)
{
// bail if we've run off the end of the buffer
RequireAction( bitPos < maxPos, status = kALAC_ParamError; goto Exit; );
m = (mb)>>QBSHIFT;
k = lg3a(m);
k = arithmin(k, kb_local);
m = (1<<k)-1;
n = dyn_get_32bit( in, &bitPos, m, k, maxSize );
// least significant bit is sign bit
{
uint32_t ndecode = n + zmode;
int32_t multiplier = (- (ndecode&1));
multiplier |= 1;
del = ((ndecode+1) >> 1) * (multiplier);
}
*outPtr++ = del;
c++;
mb = pb_local*(n+zmode) + mb - ((pb_local*mb)>>QBSHIFT);
// update mean tracking
if (n > N_MAX_MEAN_CLAMP)
mb = N_MEAN_CLAMP_VAL;
zmode = 0;
if (((mb << MMULSHIFT) < QB) && (c < numSamples))
{
zmode = 1;
k = lead(mb) - BITOFF+((mb+MOFF)>>MDENSHIFT);
mz = ((1<<k)-1) & wb_local;
n = dyn_get(in, &bitPos, mz, k);
RequireAction(c+n <= numSamples, status = kALAC_ParamError; goto Exit; );
for(j=0; j < n; j++)
{
*outPtr++ = 0;
++c;
}
if(n >= 65535)
zmode = 0;
mb = 0;
}
}
Exit:
*outNumBits = (bitPos - startPos);
BitBufferAdvance( bitstream, *outNumBits );
RequireAction( bitstream->cur <= bitstream->end, status = kALAC_ParamError; );
return status;
}

View File

@@ -0,0 +1,370 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: ag_enc.c
Contains: Adaptive Golomb encode routines.
Copyright: (c) 2001-2011 Apple, Inc.
*/
#include "aglib.h"
#include "ALACBitUtilities.h"
#include "EndianPortable.h"
#include "ALACAudioTypes.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if __GNUC__ && TARGET_OS_MAC
#if __POWERPC__
#include <ppc_intrinsics.h>
#else
#include <libkern/OSByteOrder.h>
#endif
#endif
#define CODE_TO_LONG_MAXBITS 32
#define N_MAX_MEAN_CLAMP 0xffff
#define N_MEAN_CLAMP_VAL 0xffff
#define REPORT_VAL 40
#if __GNUC__
#define ALWAYS_INLINE __attribute__((always_inline))
#else
#define ALWAYS_INLINE
#endif
/* And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this
to help the compiler out. In many cases this required manual inlining or a macro. Sorry
if it is ugly but the performance gains are well worth it.
- WSK 5/19/04
*/
// note: implementing this with some kind of "count leading zeros" assembly is a big performance win
static inline int32_t lead( int32_t m )
{
long j;
unsigned long c = (1ul << 31);
for(j=0; j < 32; j++)
{
if((c & m) != 0)
break;
c >>= 1;
}
return (j);
}
#define arithmin(a, b) ((a) < (b) ? (a) : (b))
static inline int32_t ALWAYS_INLINE lg3a( int32_t x)
{
int32_t result;
x += 3;
result = lead(x);
return 31 - result;
}
static inline int32_t ALWAYS_INLINE abs_func( int32_t a )
{
// note: the CW PPC intrinsic __abs() turns into these instructions so no need to try and use it
int32_t isneg = a >> 31;
int32_t xorval = a ^ isneg;
int32_t result = xorval-isneg;
return result;
}
static inline uint32_t ALWAYS_INLINE read32bit( uint8_t * buffer )
{
// embedded CPUs typically can't read unaligned 32-bit words so just read the bytes
uint32_t value;
value = ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) |
((uint32_t)buffer[2] << 8) | (uint32_t)buffer[3];
return value;
}
#if PRAGMA_MARK
#pragma mark -
#endif
static inline int32_t dyn_code(int32_t m, int32_t k, int32_t n, uint32_t *outNumBits)
{
uint32_t div, mod, de;
uint32_t numBits;
uint32_t value;
//Assert( n >= 0 );
div = n/m;
if(div >= MAX_PREFIX_16)
{
numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16;
value = (((1<<MAX_PREFIX_16)-1)<<MAX_DATATYPE_BITS_16) + n;
}
else
{
mod = n%m;
de = (mod == 0);
numBits = div + k + 1 - de;
value = (((1<<div)-1)<<(numBits-div)) + mod + 1 - de;
// if coding this way is bigger than doing escape, then do escape
if (numBits > MAX_PREFIX_16 + MAX_DATATYPE_BITS_16)
{
numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16;
value = (((1<<MAX_PREFIX_16)-1)<<MAX_DATATYPE_BITS_16) + n;
}
}
*outNumBits = numBits;
return (int32_t) value;
}
static inline int32_t dyn_code_32bit(int32_t maxbits, uint32_t m, uint32_t k, uint32_t n, uint32_t *outNumBits, uint32_t *outValue, uint32_t *overflow, uint32_t *overflowbits)
{
uint32_t div, mod, de;
uint32_t numBits;
uint32_t value;
int32_t didOverflow = 0;
div = n/m;
if (div < MAX_PREFIX_32)
{
mod = n - (m * div);
de = (mod == 0);
numBits = div + k + 1 - de;
value = (((1<<div)-1)<<(numBits-div)) + mod + 1 - de;
if (numBits > 25)
goto codeasescape;
}
else
{
codeasescape:
numBits = MAX_PREFIX_32;
value = (((1<<MAX_PREFIX_32)-1));
*overflow = n;
*overflowbits = maxbits;
didOverflow = 1;
}
*outNumBits = numBits;
*outValue = value;
return didOverflow;
}
static inline void ALWAYS_INLINE dyn_jam_noDeref(unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
{
uint32_t *i = (uint32_t *)(out + (bitPos >> 3));
uint32_t mask;
uint32_t curr;
uint32_t shift;
//Assert( numBits <= 32 );
curr = *i;
curr = Swap32NtoB( curr );
shift = 32 - (bitPos & 7) - numBits;
mask = ~0u >> (32 - numBits); // mask must be created in two steps to avoid compiler sequencing ambiguity
mask <<= shift;
value = (value << shift) & mask;
value |= curr & ~mask;
*i = Swap32BtoN( value );
}
static inline void ALWAYS_INLINE dyn_jam_noDeref_large(unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
{
uint32_t * i = (uint32_t *)(out + (bitPos>>3));
uint32_t w;
uint32_t curr;
uint32_t mask;
int32_t shiftvalue = (32 - (bitPos&7) - numBits);
//Assert(numBits <= 32);
curr = *i;
curr = Swap32NtoB( curr );
if (shiftvalue < 0)
{
uint8_t tailbyte;
uint8_t *tailptr;
w = value >> -shiftvalue;
mask = ~0u >> -shiftvalue;
w |= (curr & ~mask);
tailptr = ((uint8_t *)i) + 4;
tailbyte = (value << ((8+shiftvalue))) & 0xff;
*tailptr = (uint8_t)tailbyte;
}
else
{
mask = ~0u >> (32 - numBits);
mask <<= shiftvalue; // mask must be created in two steps to avoid compiler sequencing ambiguity
w = (value << shiftvalue) & mask;
w |= curr & ~mask;
}
*i = Swap32BtoN( w );
}
int32_t dyn_comp( AGParamRecPtr params, int32_t * pc, BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits )
{
unsigned char * out;
uint32_t bitPos, startPos;
uint32_t m, k, n, c, mz, nz;
uint32_t numBits;
uint32_t value;
int32_t del, zmode;
uint32_t overflow, overflowbits;
int32_t status;
// shadow the variables in params so there's not the dereferencing overhead
uint32_t mb, pb, kb, wb;
int32_t rowPos = 0;
int32_t rowSize = params->sw;
int32_t rowJump = (params->fw) - rowSize;
int32_t * inPtr = pc;
*outNumBits = 0;
RequireAction( (bitSize >= 1) && (bitSize <= 32), return kALAC_ParamError; );
out = bitstream->cur;
startPos = bitstream->bitIndex;
bitPos = startPos;
mb = params->mb = params->mb0;
pb = params->pb;
kb = params->kb;
wb = params->wb;
zmode = 0;
c=0;
status = ALAC_noErr;
while (c < numSamples)
{
m = mb >> QBSHIFT;
k = lg3a(m);
if ( k > kb)
{
k = kb;
}
m = (1<<k)-1;
del = *inPtr++;
rowPos++;
n = (abs_func(del) << 1) - ((del >> 31) & 1) - zmode;
//Assert( 32-lead(n) <= bitSize );
if ( dyn_code_32bit(bitSize, m, k, n, &numBits, &value, &overflow, &overflowbits) )
{
dyn_jam_noDeref(out, bitPos, numBits, value);
bitPos += numBits;
dyn_jam_noDeref_large(out, bitPos, overflowbits, overflow);
bitPos += overflowbits;
}
else
{
dyn_jam_noDeref(out, bitPos, numBits, value);
bitPos += numBits;
}
c++;
if ( rowPos >= rowSize)
{
rowPos = 0;
inPtr += rowJump;
}
mb = pb * (n + zmode) + mb - ((pb *mb)>>QBSHIFT);
// update mean tracking if it's overflowed
if (n > N_MAX_MEAN_CLAMP)
mb = N_MEAN_CLAMP_VAL;
zmode = 0;
RequireAction(c <= numSamples, status = kALAC_ParamError; goto Exit; );
if (((mb << MMULSHIFT) < QB) && (c < numSamples))
{
zmode = 1;
nz = 0;
while(c<numSamples && *inPtr == 0)
{
/* Take care of wrap-around globals. */
++inPtr;
++nz;
++c;
if ( ++rowPos >= rowSize)
{
rowPos = 0;
inPtr += rowJump;
}
if(nz >= 65535)
{
zmode = 0;
break;
}
}
k = lead(mb) - BITOFF+((mb+MOFF)>>MDENSHIFT);
mz = ((1<<k)-1) & wb;
value = dyn_code(mz, k, nz, &numBits);
dyn_jam_noDeref(out, bitPos, numBits, value);
bitPos += numBits;
mb = 0;
}
}
*outNumBits = (bitPos - startPos);
BitBufferAdvance( bitstream, *outNumBits );
Exit:
return status;
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: aglib.h
Copyright: (C) 2001-2011 Apple, Inc.
*/
#ifndef AGLIB_H
#define AGLIB_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define QBSHIFT 9
#define QB (1<<QBSHIFT)
#define PB0 40
#define MB0 10
#define KB0 14
#define MAX_RUN_DEFAULT 255
#define MMULSHIFT 2
#define MDENSHIFT (QBSHIFT - MMULSHIFT - 1)
#define MOFF ((1<<(MDENSHIFT-2)))
#define BITOFF 24
/* Max. prefix of 1's. */
#define MAX_PREFIX_16 9
#define MAX_PREFIX_TOLONG_16 15
#define MAX_PREFIX_32 9
/* Max. bits in 16-bit data type */
#define MAX_DATATYPE_BITS_16 16
typedef struct AGParamRec
{
uint32_t mb, mb0, pb, kb, wb, qb;
uint32_t fw, sw;
uint32_t maxrun;
// fw = 1, sw = 1;
} AGParamRec, *AGParamRecPtr;
struct BitBuffer;
void set_standard_ag_params(AGParamRecPtr params, uint32_t fullwidth, uint32_t sectorwidth);
void set_ag_params(AGParamRecPtr params, uint32_t m, uint32_t p, uint32_t k, uint32_t f, uint32_t s, uint32_t maxrun);
int32_t dyn_comp(AGParamRecPtr params, int32_t * pc, struct BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits);
int32_t dyn_decomp(AGParamRecPtr params, struct BitBuffer * bitstream, int32_t * pc, int32_t numSamples, int32_t maxSize, uint32_t * outNumBits);
#ifdef __cplusplus
}
#endif
#endif //#ifndef AGLIB_H

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ag_dec.c" />
<ClCompile Include="ag_enc.c" />
<ClCompile Include="ALACBitUtilities.c" />
<ClCompile Include="ALACDecoder.cpp" />
<ClCompile Include="ALACEncoder.cpp" />
<ClCompile Include="dp_dec.c" />
<ClCompile Include="dp_enc.c" />
<ClCompile Include="EndianPortable.c" />
<ClCompile Include="matrix_dec.c" />
<ClCompile Include="matrix_enc.c" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{73ae36f4-6af9-46b0-a682-4321d57ef8e7}</ProjectGuid>
<RootNamespace>alac</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
<IntDir>build\$(Configuration)\$(Platform)</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<OutDir>..\targets\win32\x86</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<OutDir>..\targets\win32\$(Platform)</OutDir>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<Link>
<SubSystem>
</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,42 @@
#!/bin/bash
list="x86_64-linux-gnu-gcc i686-linux-gnu-gcc arm-linux-gnueabi-gcc aarch64-linux-gnu-gcc sparc64-linux-gnu-gcc mips-linux-gnu-gcc powerpc-linux-gnu-gcc"
declare -A alias=( [i686-linux-gnu-gcc]=x86-linux-gnu-gcc )
declare -a compilers
IFS= read -ra candidates <<< "$list"
# first select platforms/compilers
for cc in ${candidates[@]}
do
# check compiler first
if ! command -v $cc &> /dev/null; then
continue
fi
if [[ $# == 0 ]]; then
compilers+=($cc)
continue
fi
for arg in $@
do
if [[ ${alias[$cc]:-$cc} =~ $arg ]]; then
compilers+=($cc)
fi
done
done
for cc in ${compilers[@]}
do
IFS=- read -r platform host dummy <<< ${alias[$cc]:-$cc}
make clean && make CC=$cc
mkdir -p ../targets/$host/$platform
cp libalac.a $_
done
mkdir -p ../targets/include
cp ALACAudioTypes.h $_
cp ALACEncoder.h $_
cp ALACDecoder.h $_

View File

@@ -0,0 +1,381 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: dp_dec.c
Contains: Dynamic Predictor decode routines
Copyright: (c) 2001-2011 Apple, Inc.
*/
#include "dplib.h"
#include <string.h>
#if __GNUC__
#define ALWAYS_INLINE __attribute__((always_inline))
#else
#define ALWAYS_INLINE
#endif
#if TARGET_CPU_PPC && (__MWERKS__ >= 0x3200)
// align loops to a 16 byte boundary to make the G5 happy
#pragma function_align 16
#define LOOP_ALIGN asm { align 16 }
#else
#define LOOP_ALIGN
#endif
static inline int32_t ALWAYS_INLINE sign_of_int( int32_t i )
{
int32_t negishift;
negishift = ((uint32_t)-i) >> 31;
return negishift | (i >> 31);
}
void unpc_block( int32_t * pc1, int32_t * out, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift )
{
register int16_t a0, a1, a2, a3;
register int32_t b0, b1, b2, b3;
int32_t j, k, lim;
int32_t sum1, sg, sgn, top, dd;
int32_t * pout;
int32_t del, del0;
uint32_t chanshift = 32 - chanbits;
int32_t denhalf = 1<<(denshift-1);
out[0] = pc1[0];
if ( numactive == 0 )
{
// just copy if numactive == 0 (but don't bother if in/out pointers the same)
if ( (num > 1) && (pc1 != out) )
memcpy( &out[1], &pc1[1], (num - 1) * sizeof(int32_t) );
return;
}
if ( numactive == 31 )
{
// short-circuit if numactive == 31
int32_t prev;
/* this code is written such that the in/out buffers can be the same
to conserve buffer space on embedded devices like the iPod
(original code)
for ( j = 1; j < num; j++ )
del = pc1[j] + out[j-1];
out[j] = (del << chanshift) >> chanshift;
*/
prev = out[0];
for ( j = 1; j < num; j++ )
{
del = pc1[j] + prev;
prev = (del << chanshift) >> chanshift;
out[j] = prev;
}
return;
}
for ( j = 1; j <= numactive; j++ )
{
del = pc1[j] + out[j-1];
out[j] = (del << chanshift) >> chanshift;
}
lim = numactive + 1;
if ( numactive == 4 )
{
// optimization for numactive == 4
register int16_t a0, a1, a2, a3;
register int32_t b0, b1, b2, b3;
a0 = coefs[0];
a1 = coefs[1];
a2 = coefs[2];
a3 = coefs[3];
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = out[j - lim];
pout = out + j - 1;
b0 = top - pout[0];
b1 = top - pout[-1];
b2 = top - pout[-2];
b3 = top - pout[-3];
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3) >> denshift;
del = pc1[j];
del0 = del;
sg = sign_of_int(del);
del += top + sum1;
out[j] = (del << chanshift) >> chanshift;
if ( sg > 0 )
{
sgn = sign_of_int( b3 );
a3 -= sgn;
del0 -= (4 - 3) * ((sgn * b3) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b2 );
a2 -= sgn;
del0 -= (4 - 2) * ((sgn * b2) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b1 );
a1 -= sgn;
del0 -= (4 - 1) * ((sgn * b1) >> denshift);
if ( del0 <= 0 )
continue;
a0 -= sign_of_int( b0 );
}
else if ( sg < 0 )
{
// note: to avoid unnecessary negations, we flip the value of "sgn"
sgn = -sign_of_int( b3 );
a3 -= sgn;
del0 -= (4 - 3) * ((sgn * b3) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b2 );
a2 -= sgn;
del0 -= (4 - 2) * ((sgn * b2) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b1 );
a1 -= sgn;
del0 -= (4 - 1) * ((sgn * b1) >> denshift);
if ( del0 >= 0 )
continue;
a0 += sign_of_int( b0 );
}
}
coefs[0] = a0;
coefs[1] = a1;
coefs[2] = a2;
coefs[3] = a3;
}
else if ( numactive == 8 )
{
register int16_t a4, a5, a6, a7;
register int32_t b4, b5, b6, b7;
// optimization for numactive == 8
a0 = coefs[0];
a1 = coefs[1];
a2 = coefs[2];
a3 = coefs[3];
a4 = coefs[4];
a5 = coefs[5];
a6 = coefs[6];
a7 = coefs[7];
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = out[j - lim];
pout = out + j - 1;
b0 = top - (*pout--);
b1 = top - (*pout--);
b2 = top - (*pout--);
b3 = top - (*pout--);
b4 = top - (*pout--);
b5 = top - (*pout--);
b6 = top - (*pout--);
b7 = top - (*pout);
pout += 8;
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3
- a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift;
del = pc1[j];
del0 = del;
sg = sign_of_int(del);
del += top + sum1;
out[j] = (del << chanshift) >> chanshift;
if ( sg > 0 )
{
sgn = sign_of_int( b7 );
a7 -= sgn;
del0 -= 1 * ((sgn * b7) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b6 );
a6 -= sgn;
del0 -= 2 * ((sgn * b6) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b5 );
a5 -= sgn;
del0 -= 3 * ((sgn * b5) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b4 );
a4 -= sgn;
del0 -= 4 * ((sgn * b4) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b3 );
a3 -= sgn;
del0 -= 5 * ((sgn * b3) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b2 );
a2 -= sgn;
del0 -= 6 * ((sgn * b2) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b1 );
a1 -= sgn;
del0 -= 7 * ((sgn * b1) >> denshift);
if ( del0 <= 0 )
continue;
a0 -= sign_of_int( b0 );
}
else if ( sg < 0 )
{
// note: to avoid unnecessary negations, we flip the value of "sgn"
sgn = -sign_of_int( b7 );
a7 -= sgn;
del0 -= 1 * ((sgn * b7) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b6 );
a6 -= sgn;
del0 -= 2 * ((sgn * b6) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b5 );
a5 -= sgn;
del0 -= 3 * ((sgn * b5) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b4 );
a4 -= sgn;
del0 -= 4 * ((sgn * b4) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b3 );
a3 -= sgn;
del0 -= 5 * ((sgn * b3) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b2 );
a2 -= sgn;
del0 -= 6 * ((sgn * b2) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b1 );
a1 -= sgn;
del0 -= 7 * ((sgn * b1) >> denshift);
if ( del0 >= 0 )
continue;
a0 += sign_of_int( b0 );
}
}
coefs[0] = a0;
coefs[1] = a1;
coefs[2] = a2;
coefs[3] = a3;
coefs[4] = a4;
coefs[5] = a5;
coefs[6] = a6;
coefs[7] = a7;
}
else
{
// general case
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
sum1 = 0;
pout = out + j - 1;
top = out[j-lim];
for ( k = 0; k < numactive; k++ )
sum1 += coefs[k] * (pout[-k] - top);
del = pc1[j];
del0 = del;
sg = sign_of_int( del );
del += top + ((sum1 + denhalf) >> denshift);
out[j] = (del << chanshift) >> chanshift;
if ( sg > 0 )
{
for ( k = (numactive - 1); k >= 0; k-- )
{
dd = top - pout[-k];
sgn = sign_of_int( dd );
coefs[k] -= sgn;
del0 -= (numactive - k) * ((sgn * dd) >> denshift);
if ( del0 <= 0 )
break;
}
}
else if ( sg < 0 )
{
for ( k = (numactive - 1); k >= 0; k-- )
{
dd = top - pout[-k];
sgn = sign_of_int( dd );
coefs[k] += sgn;
del0 -= (numactive - k) * ((-sgn * dd) >> denshift);
if ( del0 >= 0 )
break;
}
}
}
}
}

View File

@@ -0,0 +1,386 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: dp_enc.c
Contains: Dynamic Predictor encode routines
Copyright: (c) 2001-2011 Apple, Inc.
*/
#include "dplib.h"
#include <string.h>
#if __GNUC__
#define ALWAYS_INLINE __attribute__((always_inline))
#else
#define ALWAYS_INLINE
#endif
#if TARGET_CPU_PPC && (__MWERKS__ >= 0x3200)
// align loops to a 16 byte boundary to make the G5 happy
#pragma function_align 16
#define LOOP_ALIGN asm { align 16 }
#else
#define LOOP_ALIGN
#endif
void init_coefs( int16_t * coefs, uint32_t denshift, int32_t numPairs )
{
int32_t k;
int32_t den = 1 << denshift;
coefs[0] = (AINIT * den) >> 4;
coefs[1] = (BINIT * den) >> 4;
coefs[2] = (CINIT * den) >> 4;
for ( k = 3; k < numPairs; k++ )
coefs[k] = 0;
}
void copy_coefs( int16_t * srcCoefs, int16_t * dstCoefs, int32_t numPairs )
{
int32_t k;
for ( k = 0; k < numPairs; k++ )
dstCoefs[k] = srcCoefs[k];
}
static inline int32_t ALWAYS_INLINE sign_of_int( int32_t i )
{
int32_t negishift;
negishift = ((uint32_t)-i) >> 31;
return negishift | (i >> 31);
}
void pc_block( int32_t * in, int32_t * pc1, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift )
{
register int16_t a0, a1, a2, a3;
register int32_t b0, b1, b2, b3;
int32_t j, k, lim;
int32_t * pin;
int32_t sum1, dd;
int32_t sg, sgn;
int32_t top;
int32_t del, del0;
uint32_t chanshift = 32 - chanbits;
int32_t denhalf = 1 << (denshift - 1);
pc1[0] = in[0];
if ( numactive == 0 )
{
// just copy if numactive == 0 (but don't bother if in/out pointers the same)
if ( (num > 1) && (in != pc1) )
memcpy( &pc1[1], &in[1], (num - 1) * sizeof(int32_t) );
return;
}
if ( numactive == 31 )
{
// short-circuit if numactive == 31
for( j = 1; j < num; j++ )
{
del = in[j] - in[j-1];
pc1[j] = (del << chanshift) >> chanshift;
}
return;
}
for ( j = 1; j <= numactive; j++ )
{
del = in[j] - in[j-1];
pc1[j] = (del << chanshift) >> chanshift;
}
lim = numactive + 1;
if ( numactive == 4 )
{
// optimization for numactive == 4
a0 = coefs[0];
a1 = coefs[1];
a2 = coefs[2];
a3 = coefs[3];
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = in[j - lim];
pin = in + j - 1;
b0 = top - pin[0];
b1 = top - pin[-1];
b2 = top - pin[-2];
b3 = top - pin[-3];
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3) >> denshift;
del = in[j] - top - sum1;
del = (del << chanshift) >> chanshift;
pc1[j] = del;
del0 = del;
sg = sign_of_int(del);
if ( sg > 0 )
{
sgn = sign_of_int( b3 );
a3 -= sgn;
del0 -= (4 - 3) * ((sgn * b3) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b2 );
a2 -= sgn;
del0 -= (4 - 2) * ((sgn * b2) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b1 );
a1 -= sgn;
del0 -= (4 - 1) * ((sgn * b1) >> denshift);
if ( del0 <= 0 )
continue;
a0 -= sign_of_int( b0 );
}
else if ( sg < 0 )
{
// note: to avoid unnecessary negations, we flip the value of "sgn"
sgn = -sign_of_int( b3 );
a3 -= sgn;
del0 -= (4 - 3) * ((sgn * b3) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b2 );
a2 -= sgn;
del0 -= (4 - 2) * ((sgn * b2) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b1 );
a1 -= sgn;
del0 -= (4 - 1) * ((sgn * b1) >> denshift);
if ( del0 >= 0 )
continue;
a0 += sign_of_int( b0 );
}
}
coefs[0] = a0;
coefs[1] = a1;
coefs[2] = a2;
coefs[3] = a3;
}
else if ( numactive == 8 )
{
// optimization for numactive == 8
register int16_t a4, a5, a6, a7;
register int32_t b4, b5, b6, b7;
a0 = coefs[0];
a1 = coefs[1];
a2 = coefs[2];
a3 = coefs[3];
a4 = coefs[4];
a5 = coefs[5];
a6 = coefs[6];
a7 = coefs[7];
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = in[j - lim];
pin = in + j - 1;
b0 = top - (*pin--);
b1 = top - (*pin--);
b2 = top - (*pin--);
b3 = top - (*pin--);
b4 = top - (*pin--);
b5 = top - (*pin--);
b6 = top - (*pin--);
b7 = top - (*pin);
pin += 8;
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3
- a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift;
del = in[j] - top - sum1;
del = (del << chanshift) >> chanshift;
pc1[j] = del;
del0 = del;
sg = sign_of_int(del);
if ( sg > 0 )
{
sgn = sign_of_int( b7 );
a7 -= sgn;
del0 -= 1 * ((sgn * b7) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b6 );
a6 -= sgn;
del0 -= 2 * ((sgn * b6) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b5 );
a5 -= sgn;
del0 -= 3 * ((sgn * b5) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b4 );
a4 -= sgn;
del0 -= 4 * ((sgn * b4) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b3 );
a3 -= sgn;
del0 -= 5 * ((sgn * b3) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b2 );
a2 -= sgn;
del0 -= 6 * ((sgn * b2) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b1 );
a1 -= sgn;
del0 -= 7 * ((sgn * b1) >> denshift);
if ( del0 <= 0 )
continue;
a0 -= sign_of_int( b0 );
}
else if ( sg < 0 )
{
// note: to avoid unnecessary negations, we flip the value of "sgn"
sgn = -sign_of_int( b7 );
a7 -= sgn;
del0 -= 1 * ((sgn * b7) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b6 );
a6 -= sgn;
del0 -= 2 * ((sgn * b6) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b5 );
a5 -= sgn;
del0 -= 3 * ((sgn * b5) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b4 );
a4 -= sgn;
del0 -= 4 * ((sgn * b4) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b3 );
a3 -= sgn;
del0 -= 5 * ((sgn * b3) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b2 );
a2 -= sgn;
del0 -= 6 * ((sgn * b2) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b1 );
a1 -= sgn;
del0 -= 7 * ((sgn * b1) >> denshift);
if ( del0 >= 0 )
continue;
a0 += sign_of_int( b0 );
}
}
coefs[0] = a0;
coefs[1] = a1;
coefs[2] = a2;
coefs[3] = a3;
coefs[4] = a4;
coefs[5] = a5;
coefs[6] = a6;
coefs[7] = a7;
}
else
{
//pc_block_general:
// general case
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = in[j - lim];
pin = in + j - 1;
sum1 = 0;
for ( k = 0; k < numactive; k++ )
sum1 -= coefs[k] * (top - pin[-k]);
del = in[j] - top - ((sum1 + denhalf) >> denshift);
del = (del << chanshift) >> chanshift;
pc1[j] = del;
del0 = del;
sg = sign_of_int( del );
if ( sg > 0 )
{
for ( k = (numactive - 1); k >= 0; k-- )
{
dd = top - pin[-k];
sgn = sign_of_int( dd );
coefs[k] -= sgn;
del0 -= (numactive - k) * ((sgn * dd) >> denshift);
if ( del0 <= 0 )
break;
}
}
else if ( sg < 0 )
{
for ( k = (numactive - 1); k >= 0; k-- )
{
dd = top - pin[-k];
sgn = sign_of_int( dd );
coefs[k] += sgn;
del0 -= (numactive - k) * ((-sgn * dd) >> denshift);
if ( del0 >= 0 )
break;
}
}
}
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: dplib.h
Contains: Dynamic Predictor routines
Copyright: Copyright (C) 2001-2011 Apple, Inc.
*/
#ifndef __DPLIB_H__
#define __DPLIB_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// defines
#define DENSHIFT_MAX 15
#define DENSHIFT_DEFAULT 9
#define AINIT 38
#define BINIT (-29)
#define CINIT (-2)
#define NUMCOEPAIRS 16
// prototypes
void init_coefs( int16_t * coefs, uint32_t denshift, int32_t numPairs );
void copy_coefs( int16_t * srcCoefs, int16_t * dstCoefs, int32_t numPairs );
// NOTE: these routines read at least "numactive" samples so the i/o buffers must be at least that big
void pc_block( int32_t * in, int32_t * pc, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift );
void unpc_block( int32_t * pc, int32_t * out, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift );
#ifdef __cplusplus
}
#endif
#endif /* __DPLIB_H__ */

View File

@@ -0,0 +1,390 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: matrix_dec.c
Contains: ALAC mixing/matrixing decode routines.
Copyright: (c) 2004-2011 Apple, Inc.
*/
#include "matrixlib.h"
#include "ALACAudioTypes.h"
// up to 24-bit "offset" macros for the individual bytes of a 20/24-bit word
#if TARGET_RT_BIG_ENDIAN
#define LBYTE 2
#define MBYTE 1
#define HBYTE 0
#else
#define LBYTE 0
#define MBYTE 1
#define HBYTE 2
#endif
/*
There is no plain middle-side option; instead there are various mixing
modes including middle-side, each lossless, as embodied in the mix()
and unmix() functions. These functions exploit a generalized middle-side
transformation:
u := [(rL + (m-r)R)/m];
v := L - R;
where [ ] denotes integer floor. The (lossless) inverse is
L = u + v - [rV/m];
R = L - v;
*/
// 16-bit routines
void unmix16( int32_t * u, int32_t * v, int16_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres )
{
int16_t * op = out;
int32_t j;
if ( mixres != 0 )
{
/* matrixed stereo */
for ( j = 0; j < numSamples; j++ )
{
int32_t l, r;
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
r = l - v[j];
op[0] = (int16_t) l;
op[1] = (int16_t) r;
op += stride;
}
}
else
{
/* Conventional separated stereo. */
for ( j = 0; j < numSamples; j++ )
{
op[0] = (int16_t) u[j];
op[1] = (int16_t) v[j];
op += stride;
}
}
}
// 20-bit routines
// - the 20 bits of data are left-justified in 3 bytes of storage but right-aligned for input/output predictor buffers
void unmix20( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres )
{
uint8_t * op = out;
int32_t j;
if ( mixres != 0 )
{
/* matrixed stereo */
for ( j = 0; j < numSamples; j++ )
{
int32_t l, r;
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
r = l - v[j];
l <<= 4;
r <<= 4;
op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((l >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((l >> 0) & 0xffu);
op += 3;
op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((r >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((r >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
else
{
/* Conventional separated stereo. */
for ( j = 0; j < numSamples; j++ )
{
int32_t val;
val = u[j] << 4;
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += 3;
val = v[j] << 4;
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
}
// 24-bit routines
// - the 24 bits of data are right-justified in the input/output predictor buffers
void unmix24( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
{
uint8_t * op = out;
int32_t shift = bytesShifted * 8;
int32_t l, r;
int32_t j, k;
if ( mixres != 0 )
{
/* matrixed stereo */
if ( bytesShifted != 0 )
{
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
r = l - v[j];
l = (l << shift) | (uint32_t) shiftUV[k + 0];
r = (r << shift) | (uint32_t) shiftUV[k + 1];
op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((l >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((l >> 0) & 0xffu);
op += 3;
op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((r >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((r >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
else
{
for ( j = 0; j < numSamples; j++ )
{
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
r = l - v[j];
op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((l >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((l >> 0) & 0xffu);
op += 3;
op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((r >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((r >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
}
else
{
/* Conventional separated stereo. */
if ( bytesShifted != 0 )
{
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = u[j];
r = v[j];
l = (l << shift) | (uint32_t) shiftUV[k + 0];
r = (r << shift) | (uint32_t) shiftUV[k + 1];
op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((l >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((l >> 0) & 0xffu);
op += 3;
op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((r >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((r >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
else
{
for ( j = 0; j < numSamples; j++ )
{
int32_t val;
val = u[j];
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += 3;
val = v[j];
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
}
}
// 32-bit routines
// - note that these really expect the internal data width to be < 32 but the arrays are 32-bit
// - otherwise, the calculations might overflow into the 33rd bit and be lost
// - therefore, these routines deal with the specified "unused lower" bytes in the "shift" buffers
void unmix32( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
{
int32_t * op = out;
int32_t shift = bytesShifted * 8;
int32_t l, r;
int32_t j, k;
if ( mixres != 0 )
{
//Assert( bytesShifted != 0 );
/* matrixed stereo with shift */
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
int32_t lt, rt;
lt = u[j];
rt = v[j];
l = lt + rt - ((mixres * rt) >> mixbits);
r = l - rt;
op[0] = (l << shift) | (uint32_t) shiftUV[k + 0];
op[1] = (r << shift) | (uint32_t) shiftUV[k + 1];
op += stride;
}
}
else
{
if ( bytesShifted == 0 )
{
/* interleaving w/o shift */
for ( j = 0; j < numSamples; j++ )
{
op[0] = u[j];
op[1] = v[j];
op += stride;
}
}
else
{
/* interleaving with shift */
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
op[0] = (u[j] << shift) | (uint32_t) shiftUV[k + 0];
op[1] = (v[j] << shift) | (uint32_t) shiftUV[k + 1];
op += stride;
}
}
}
}
// 20/24-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
void copyPredictorTo24( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples )
{
uint8_t * op = out;
int32_t j;
for ( j = 0; j < numSamples; j++ )
{
int32_t val = in[j];
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += (stride * 3);
}
}
void copyPredictorTo24Shift( int32_t * in, uint16_t * shift, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted )
{
uint8_t * op = out;
int32_t shiftVal = bytesShifted * 8;
int32_t j;
//Assert( bytesShifted != 0 );
for ( j = 0; j < numSamples; j++ )
{
int32_t val = in[j];
val = (val << shiftVal) | (uint32_t) shift[j];
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += (stride * 3);
}
}
void copyPredictorTo20( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples )
{
uint8_t * op = out;
int32_t j;
// 32-bit predictor values are right-aligned but 20-bit output values should be left-aligned
// in the 24-bit output buffer
for ( j = 0; j < numSamples; j++ )
{
int32_t val = in[j];
op[HBYTE] = (uint8_t)((val >> 12) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 4) & 0xffu);
op[LBYTE] = (uint8_t)((val << 4) & 0xffu);
op += (stride * 3);
}
}
void copyPredictorTo32( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples )
{
int32_t i, j;
// this is only a subroutine to abstract the "iPod can only output 16-bit data" problem
for ( i = 0, j = 0; i < numSamples; i++, j += stride )
out[j] = in[i];
}
void copyPredictorTo32Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted )
{
int32_t * op = out;
uint32_t shiftVal = bytesShifted * 8;
int32_t j;
//Assert( bytesShifted != 0 );
// this is only a subroutine to abstract the "iPod can only output 16-bit data" problem
for ( j = 0; j < numSamples; j++ )
{
op[0] = (in[j] << shiftVal) | (uint32_t) shift[j];
op += stride;
}
}

View File

@@ -0,0 +1,342 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: matrix_enc.c
Contains: ALAC mixing/matrixing encode routines.
Copyright: (c) 2004-2011 Apple, Inc.
*/
#include "matrixlib.h"
#include "ALACAudioTypes.h"
// up to 24-bit "offset" macros for the individual bytes of a 20/24-bit word
#if TARGET_RT_BIG_ENDIAN
#define LBYTE 2
#define MBYTE 1
#define HBYTE 0
#else
#define LBYTE 0
#define MBYTE 1
#define HBYTE 2
#endif
/*
There is no plain middle-side option; instead there are various mixing
modes including middle-side, each lossless, as embodied in the mix()
and unmix() functions. These functions exploit a generalized middle-side
transformation:
u := [(rL + (m-r)R)/m];
v := L - R;
where [ ] denotes integer floor. The (lossless) inverse is
L = u + v - [rV/m];
R = L - v;
*/
// 16-bit routines
void mix16( int16_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres )
{
int16_t * ip = in;
int32_t j;
if ( mixres != 0 )
{
int32_t mod = 1 << mixbits;
int32_t m2;
/* matrixed stereo */
m2 = mod - mixres;
for ( j = 0; j < numSamples; j++ )
{
int32_t l, r;
l = (int32_t) ip[0];
r = (int32_t) ip[1];
ip += stride;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
else
{
/* Conventional separated stereo. */
for ( j = 0; j < numSamples; j++ )
{
u[j] = (int32_t) ip[0];
v[j] = (int32_t) ip[1];
ip += stride;
}
}
}
// 20-bit routines
// - the 20 bits of data are left-justified in 3 bytes of storage but right-aligned for input/output predictor buffers
void mix20( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres )
{
int32_t l, r;
uint8_t * ip = in;
int32_t j;
if ( mixres != 0 )
{
/* matrixed stereo */
int32_t mod = 1 << mixbits;
int32_t m2 = mod - mixres;
for ( j = 0; j < numSamples; j++ )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
l = (l << 8) >> 12;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
r = (r << 8) >> 12;
ip += (stride - 1) * 3;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
else
{
/* Conventional separated stereo. */
for ( j = 0; j < numSamples; j++ )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
u[j] = (l << 8) >> 12;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
v[j] = (r << 8) >> 12;
ip += (stride - 1) * 3;
}
}
}
// 24-bit routines
// - the 24 bits of data are right-justified in the input/output predictor buffers
void mix24( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
{
int32_t l, r;
uint8_t * ip = in;
int32_t shift = bytesShifted * 8;
uint32_t mask = (1ul << shift) - 1;
int32_t j, k;
if ( mixres != 0 )
{
/* matrixed stereo */
int32_t mod = 1 << mixbits;
int32_t m2 = mod - mixres;
if ( bytesShifted != 0 )
{
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
l = (l << 8) >> 8;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
r = (r << 8) >> 8;
ip += (stride - 1) * 3;
shiftUV[k + 0] = (uint16_t)(l & mask);
shiftUV[k + 1] = (uint16_t)(r & mask);
l >>= shift;
r >>= shift;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
else
{
for ( j = 0; j < numSamples; j++ )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
l = (l << 8) >> 8;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
r = (r << 8) >> 8;
ip += (stride - 1) * 3;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
}
else
{
/* Conventional separated stereo. */
if ( bytesShifted != 0 )
{
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
l = (l << 8) >> 8;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
r = (r << 8) >> 8;
ip += (stride - 1) * 3;
shiftUV[k + 0] = (uint16_t)(l & mask);
shiftUV[k + 1] = (uint16_t)(r & mask);
l >>= shift;
r >>= shift;
u[j] = l;
v[j] = r;
}
}
else
{
for ( j = 0; j < numSamples; j++ )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
u[j] = (l << 8) >> 8;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
v[j] = (r << 8) >> 8;
ip += (stride - 1) * 3;
}
}
}
}
// 32-bit routines
// - note that these really expect the internal data width to be < 32 but the arrays are 32-bit
// - otherwise, the calculations might overflow into the 33rd bit and be lost
// - therefore, these routines deal with the specified "unused lower" bytes in the "shift" buffers
void mix32( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
{
int32_t * ip = in;
int32_t shift = bytesShifted * 8;
uint32_t mask = (1ul << shift) - 1;
int32_t l, r;
int32_t j, k;
if ( mixres != 0 )
{
int32_t mod = 1 << mixbits;
int32_t m2;
//Assert( bytesShifted != 0 );
/* matrixed stereo with shift */
m2 = mod - mixres;
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = ip[0];
r = ip[1];
ip += stride;
shiftUV[k + 0] = (uint16_t)(l & mask);
shiftUV[k + 1] = (uint16_t)(r & mask);
l >>= shift;
r >>= shift;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
else
{
if ( bytesShifted == 0 )
{
/* de-interleaving w/o shift */
for ( j = 0; j < numSamples; j++ )
{
u[j] = ip[0];
v[j] = ip[1];
ip += stride;
}
}
else
{
/* de-interleaving with shift */
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = ip[0];
r = ip[1];
ip += stride;
shiftUV[k + 0] = (uint16_t)(l & mask);
shiftUV[k + 1] = (uint16_t)(r & mask);
l >>= shift;
r >>= shift;
u[j] = l;
v[j] = r;
}
}
}
}
// 20/24-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
void copy20ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples )
{
uint8_t * ip = in;
int32_t j;
for ( j = 0; j < numSamples; j++ )
{
int32_t val;
// 20-bit values are left-aligned in the 24-bit input buffer but right-aligned in the 32-bit output buffer
val = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
out[j] = (val << 8) >> 12;
ip += stride * 3;
}
}
void copy24ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples )
{
uint8_t * ip = in;
int32_t j;
for ( j = 0; j < numSamples; j++ )
{
int32_t val;
val = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
out[j] = (val << 8) >> 8;
ip += stride * 3;
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: matrixlib.h
Contains: ALAC mixing/matrixing routines to/from 32-bit predictor buffers.
Copyright: Copyright (C) 2004 to 2011 Apple, Inc.
*/
#ifndef __MATRIXLIB_H
#define __MATRIXLIB_H
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// 16-bit routines
void mix16( int16_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres );
void unmix16( int32_t * u, int32_t * v, int16_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres );
// 20-bit routines
void mix20( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres );
void unmix20( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres );
// 24-bit routines
// - 24-bit data sometimes compresses better by shifting off the bottom byte so these routines deal with
// the specified "unused lower bytes" in the combined "shift" buffer
void mix24( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
void unmix24( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
// 32-bit routines
// - note that these really expect the internal data width to be < 32-bit but the arrays are 32-bit
// - otherwise, the calculations might overflow into the 33rd bit and be lost
// - therefore, these routines deal with the specified "unused lower" bytes in the combined "shift" buffer
void mix32( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
void unmix32( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
// 20/24/32-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
void copy20ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples );
void copy24ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples );
void copyPredictorTo24( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples );
void copyPredictorTo24Shift( int32_t * in, uint16_t * shift, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted );
void copyPredictorTo20( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples );
void copyPredictorTo32( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples );
void copyPredictorTo32Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted );
#ifdef __cplusplus
}
#endif
#endif /* __MATRIXLIB_H */

View File

@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alacConvert", "alacConvert.vcproj", "{B9B08911-AF77-447E-A4DD-692AFFA0E346}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Debug|Win32.ActiveCfg = Debug|Win32
{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Debug|Win32.Build.0 = Debug|Win32
{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Release|Win32.ActiveCfg = Release|Win32
{B9B08911-AF77-447E-A4DD-692AFFA0E346}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,379 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="alacConvert"
ProjectGUID="{B9B08911-AF77-447E-A4DD-692AFFA0E346}"
RootNamespace="alacConvert"
Keyword="ManagedCProj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
ManagedExtensions="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\codec;.\"
PreprocessorDefinitions="WIN32;_DEBUG;TARGET_OS_WIN32"
RuntimeLibrary="3"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="2"
GenerateDebugInformation="true"
AssemblyDebug="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
ManagedExtensions="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG"
RuntimeLibrary="2"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="1"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\codec\ag_dec.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\ag_enc.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\ALACBitUtilities.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\ALACDecoder.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\ALACEncoder.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
/>
</FileConfiguration>
</File>
<File
RelativePath="CAFFileALAC.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\dp_dec.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\dp_enc.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\EndianPortable.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="main.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\matrix_dec.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\codec\matrix_enc.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
CompileAs="2"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\codec\aglib.h"
>
</File>
<File
RelativePath="..\codec\ALACAudioTypes.h"
>
</File>
<File
RelativePath="..\codec\ALACBitUtilities.h"
>
</File>
<File
RelativePath="..\codec\ALACDecoder.h"
>
</File>
<File
RelativePath="..\codec\ALACEncoder.h"
>
</File>
<File
RelativePath="CAFFileALAC.h"
>
</File>
<File
RelativePath="..\codec\dplib.h"
>
</File>
<File
RelativePath="..\codec\EndianPortable.h"
>
</File>
<File
RelativePath="..\codec\matrixlib.h"
>
</File>
<File
RelativePath=".\stdint.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,362 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 42;
objects = {
/* Begin PBXBuildFile section */
071120831405C91B007FF1B0 /* ALACBitUtilities.c in Sources */ = {isa = PBXBuildFile; fileRef = 071120811405C91B007FF1B0 /* ALACBitUtilities.c */; };
074B586A1405B97E0060A703 /* ag_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58611405B97E0060A703 /* ag_dec.c */; };
074B586B1405B97E0060A703 /* ag_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58621405B97E0060A703 /* ag_enc.c */; };
074B586D1405B97E0060A703 /* dp_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58641405B97E0060A703 /* dp_dec.c */; };
074B586E1405B97E0060A703 /* dp_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58651405B97E0060A703 /* dp_enc.c */; };
074B58791405B98B0060A703 /* matrix_dec.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58751405B98B0060A703 /* matrix_dec.c */; };
074B587A1405B98B0060A703 /* matrix_enc.c in Sources */ = {isa = PBXBuildFile; fileRef = 074B58761405B98B0060A703 /* matrix_enc.c */; };
075CBE1E142184CB0089DFF0 /* CAFFileALAC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 075CBE1D142184CB0089DFF0 /* CAFFileALAC.cpp */; };
07B7F449141999F800035453 /* ALACDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07B7F445141999F800035453 /* ALACDecoder.cpp */; };
07B7F44B141999F800035453 /* ALACEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07B7F447141999F800035453 /* ALACEncoder.cpp */; };
07E06D00142968F2002489A3 /* EndianPortable.c in Sources */ = {isa = PBXBuildFile; fileRef = 07E06CFE142968F2002489A3 /* EndianPortable.c */; };
A98FBFAD06EBB5AB00E7B080 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A98FBFAC06EBB5AB00E7B080 /* main.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
8DD76FAF0486AB0100D96B5E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
071120811405C91B007FF1B0 /* ALACBitUtilities.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ALACBitUtilities.c; sourceTree = "<group>"; };
071120821405C91B007FF1B0 /* ALACBitUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACBitUtilities.h; sourceTree = "<group>"; };
074B58611405B97E0060A703 /* ag_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ag_dec.c; sourceTree = "<group>"; };
074B58621405B97E0060A703 /* ag_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ag_enc.c; sourceTree = "<group>"; };
074B58631405B97E0060A703 /* aglib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aglib.h; sourceTree = "<group>"; };
074B58641405B97E0060A703 /* dp_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dp_dec.c; sourceTree = "<group>"; };
074B58651405B97E0060A703 /* dp_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dp_enc.c; sourceTree = "<group>"; };
074B58741405B98B0060A703 /* dplib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dplib.h; sourceTree = "<group>"; };
074B58751405B98B0060A703 /* matrix_dec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix_dec.c; sourceTree = "<group>"; };
074B58761405B98B0060A703 /* matrix_enc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix_enc.c; sourceTree = "<group>"; };
074B587B1405B9920060A703 /* matrixlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrixlib.h; sourceTree = "<group>"; };
075CBE12141EC2080089DFF0 /* CAFFileALAC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAFFileALAC.h; sourceTree = "<group>"; };
075CBE1D142184CB0089DFF0 /* CAFFileALAC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CAFFileALAC.cpp; sourceTree = "<group>"; };
075CBE1F142187450089DFF0 /* ALACAudioTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACAudioTypes.h; sourceTree = "<group>"; };
07B7F445141999F800035453 /* ALACDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ALACDecoder.cpp; sourceTree = "<group>"; };
07B7F446141999F800035453 /* ALACDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACDecoder.h; sourceTree = "<group>"; };
07B7F447141999F800035453 /* ALACEncoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ALACEncoder.cpp; sourceTree = "<group>"; };
07B7F448141999F800035453 /* ALACEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ALACEncoder.h; sourceTree = "<group>"; };
07E06CFE142968F2002489A3 /* EndianPortable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = EndianPortable.c; sourceTree = "<group>"; };
07E06CFF142968F2002489A3 /* EndianPortable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EndianPortable.h; sourceTree = "<group>"; };
8DD76FB20486AB0100D96B5E /* alacconvert */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = alacconvert; sourceTree = BUILT_PRODUCTS_DIR; };
A98FBFAC06EBB5AB00E7B080 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
074B58601405B8160060A703 /* codec */ = {
isa = PBXGroup;
children = (
074B58611405B97E0060A703 /* ag_dec.c */,
074B58621405B97E0060A703 /* ag_enc.c */,
074B58631405B97E0060A703 /* aglib.h */,
074B58641405B97E0060A703 /* dp_dec.c */,
074B58651405B97E0060A703 /* dp_enc.c */,
074B58741405B98B0060A703 /* dplib.h */,
074B58751405B98B0060A703 /* matrix_dec.c */,
074B58761405B98B0060A703 /* matrix_enc.c */,
074B587B1405B9920060A703 /* matrixlib.h */,
075CBE1F142187450089DFF0 /* ALACAudioTypes.h */,
071120811405C91B007FF1B0 /* ALACBitUtilities.c */,
071120821405C91B007FF1B0 /* ALACBitUtilities.h */,
07B7F445141999F800035453 /* ALACDecoder.cpp */,
07B7F446141999F800035453 /* ALACDecoder.h */,
07B7F447141999F800035453 /* ALACEncoder.cpp */,
07B7F448141999F800035453 /* ALACEncoder.h */,
07E06CFE142968F2002489A3 /* EndianPortable.c */,
07E06CFF142968F2002489A3 /* EndianPortable.h */,
);
name = codec;
path = ../codec;
sourceTree = SOURCE_ROOT;
};
08FB7794FE84155DC02AAC07 /* ALACconvert */ = {
isa = PBXGroup;
children = (
08FB7795FE84155DC02AAC07 /* Source */,
1AB674ADFE9D54B511CA2CBB /* Products */,
);
name = ALACconvert;
sourceTree = "<group>";
};
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
A98FBFAC06EBB5AB00E7B080 /* main.cpp */,
075CBE12141EC2080089DFF0 /* CAFFileALAC.h */,
075CBE1D142184CB0089DFF0 /* CAFFileALAC.cpp */,
074B58601405B8160060A703 /* codec */,
);
name = Source;
sourceTree = "<group>";
};
1AB674ADFE9D54B511CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
8DD76FB20486AB0100D96B5E /* alacconvert */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
8DD76FAA0486AB0100D96B5E /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
8DD76FA90486AB0100D96B5E /* ALACconvert */ = {
isa = PBXNativeTarget;
buildConfigurationList = A9E1644A087DFBDE006BF7C2 /* Build configuration list for PBXNativeTarget "ALACconvert" */;
buildPhases = (
8DD76FAA0486AB0100D96B5E /* Headers */,
8DD76FAB0486AB0100D96B5E /* Sources */,
8DD76FAD0486AB0100D96B5E /* Frameworks */,
8DD76FAE0486AB0100D96B5E /* Rez */,
8DD76FAF0486AB0100D96B5E /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = ALACconvert;
productInstallPath = "$(HOME)/bin";
productName = ALACconvert;
productReference = 8DD76FB20486AB0100D96B5E /* alacconvert */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = A9E1644E087DFBDE006BF7C2 /* Build configuration list for PBXProject "ALACconvert" */;
compatibilityVersion = "Xcode 2.4";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
en,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* ALACconvert */;
projectDirPath = "";
projectRoot = "";
targets = (
8DD76FA90486AB0100D96B5E /* ALACconvert */,
);
};
/* End PBXProject section */
/* Begin PBXRezBuildPhase section */
8DD76FAE0486AB0100D96B5E /* Rez */ = {
isa = PBXRezBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXRezBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
8DD76FAB0486AB0100D96B5E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A98FBFAD06EBB5AB00E7B080 /* main.cpp in Sources */,
074B586A1405B97E0060A703 /* ag_dec.c in Sources */,
074B586B1405B97E0060A703 /* ag_enc.c in Sources */,
074B586D1405B97E0060A703 /* dp_dec.c in Sources */,
074B586E1405B97E0060A703 /* dp_enc.c in Sources */,
074B58791405B98B0060A703 /* matrix_dec.c in Sources */,
074B587A1405B98B0060A703 /* matrix_enc.c in Sources */,
071120831405C91B007FF1B0 /* ALACBitUtilities.c in Sources */,
07B7F449141999F800035453 /* ALACDecoder.cpp in Sources */,
07B7F44B141999F800035453 /* ALACEncoder.cpp in Sources */,
075CBE1E142184CB0089DFF0 /* CAFFileALAC.cpp in Sources */,
07E06D00142968F2002489A3 /* EndianPortable.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
A9E1644B087DFBDE006BF7C2 /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
COPY_PHASE_STRIP = NO;
DEBUGGING_SYMBOLS = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_ENABLE_TRIGRAPHS = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
GCC_WARN_UNKNOWN_PRAGMAS = NO;
HEADER_SEARCH_PATHS = "";
INSTALL_PATH = "$(HOME)/bin";
LIBRARY_SEARCH_PATHS = "";
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = alacconvert;
REZ_EXECUTABLE = YES;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
ZERO_LINK = NO;
};
name = Development;
};
A9E1644C087DFBDE006BF7C2 /* Deployment - Fat */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
COPY_PHASE_STRIP = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_ENABLE_TRIGRAPHS = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
GCC_WARN_UNKNOWN_PRAGMAS = NO;
HEADER_SEARCH_PATHS = "";
INSTALL_PATH = "$(HOME)/bin";
LIBRARY_SEARCH_PATHS = "";
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = alacconvert;
REZ_EXECUTABLE = YES;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
ZERO_LINK = NO;
};
name = "Deployment - Fat";
};
A9E1644D087DFBDE006BF7C2 /* Default */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
FRAMEWORK_SEARCH_PATHS = "";
GCC_ENABLE_TRIGRAPHS = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PRECOMPILE_PREFIX_HEADER = NO;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
GCC_WARN_UNKNOWN_PRAGMAS = NO;
HEADER_SEARCH_PATHS = "";
INSTALL_PATH = "$(HOME)/bin";
LIBRARY_SEARCH_PATHS = "";
OTHER_CFLAGS = "";
OTHER_LDFLAGS = "";
OTHER_REZFLAGS = "";
PRODUCT_NAME = alacconvert;
REZ_EXECUTABLE = YES;
SECTORDER_FLAGS = "";
WARNING_CFLAGS = (
"-Wmost",
"-Wno-four-char-constants",
"-Wno-unknown-pragmas",
);
};
name = Default;
};
A9E1644F087DFBDE006BF7C2 /* Development */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
HEADER_SEARCH_PATHS = "";
};
name = Development;
};
A9E16450087DFBDE006BF7C2 /* Deployment - Fat */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
HEADER_SEARCH_PATHS = "";
};
name = "Deployment - Fat";
};
A9E16451087DFBDE006BF7C2 /* Default */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
HEADER_SEARCH_PATHS = "";
};
name = Default;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
A9E1644A087DFBDE006BF7C2 /* Build configuration list for PBXNativeTarget "ALACconvert" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A9E1644B087DFBDE006BF7C2 /* Development */,
A9E1644C087DFBDE006BF7C2 /* Deployment - Fat */,
A9E1644D087DFBDE006BF7C2 /* Default */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Default;
};
A9E1644E087DFBDE006BF7C2 /* Build configuration list for PBXProject "ALACconvert" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A9E1644F087DFBDE006BF7C2 /* Development */,
A9E16450087DFBDE006BF7C2 /* Deployment - Fat */,
A9E16451087DFBDE006BF7C2 /* Default */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Default;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

View File

@@ -0,0 +1,456 @@
/*
Copyright © 2011 Apple Inc. All rights reserved.
IMPORTANT: This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//
// CAFFileALAC.cpp
//
// Copyright 2011 Apple Inc. All rights reserved.
//
#include <stdio.h>
#include "CAFFileALAC.h"
#include "EndianPortable.h"
#define kSizeOfChanAtomPlusChannelLayout 24
int32_t FindCAFFPacketTableStart(FILE * inputFile, int32_t * paktPos, int32_t * paktSize)
{
// returns the absolute position within the file
int32_t currentPosition = ftell(inputFile); // record the current position
uint8_t theReadBuffer[12];
uint32_t chunkType = 0, chunkSize = 0;
bool done = false;
int32_t bytesRead = 8;
fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
while (!done && bytesRead > 0) // no file size here
{
bytesRead = fread(theReadBuffer, 1, 12, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch(chunkType)
{
case 'pakt':
*paktPos = ftell(inputFile) + kMinCAFFPacketTableHeaderSize;
// big endian size
*paktSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
done = true;
break;
default:
chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
fseek(inputFile, currentPosition, SEEK_SET); // start at 0
return 0;
}
void WriteCAFFcaffChunk(FILE * outputFile)
{
uint8_t theReadBuffer[8] = {'c', 'a', 'f', 'f', 0, 1, 0, 0};
fwrite(theReadBuffer, 1, 8, outputFile);
}
void WriteCAFFdescChunk(FILE * outputFile, AudioFormatDescription theOutputFormat)
{
port_CAFAudioDescription theDescription;
uint32_t tempFormatFlags = theOutputFormat.mFormatFlags;
uint8_t theReadBuffer[12] = {'d', 'e', 's', 'c', 0, 0, 0, 0, 0, 0, 0, 0};
if (theOutputFormat.mFormatID == kALACFormatLinearPCM)
{
if (kALACFormatFlagsNativeEndian > 0) // kALACFormatFlagsNativeEndian is 2 on a big endian machine, 0 on little
{
tempFormatFlags = 0;
}
else
{
tempFormatFlags = k_port_CAFLinearPCMFormatFlagIsLittleEndian;
}
}
theDescription.mSampleRate = SwapFloat64NtoB(theOutputFormat.mSampleRate);
theDescription.mFormatID = Swap32NtoB(theOutputFormat.mFormatID);
theDescription.mFormatFlags = Swap32NtoB(tempFormatFlags);
theDescription.mBytesPerPacket = Swap32NtoB(theOutputFormat.mBytesPerPacket);
theDescription.mFramesPerPacket = Swap32NtoB(theOutputFormat.mFramesPerPacket);
theDescription.mChannelsPerFrame = Swap32NtoB(theOutputFormat.mChannelsPerFrame);
theDescription.mBitsPerChannel = Swap32NtoB(theOutputFormat.mBitsPerChannel);
theReadBuffer[11] = sizeof(port_CAFAudioDescription);
fwrite(theReadBuffer, 1, 12, outputFile);
fwrite(&theDescription, 1, sizeof(port_CAFAudioDescription), outputFile);
}
void WriteCAFFdataChunk(FILE * outputFile)
{
uint8_t theReadBuffer[16] = {'d', 'a', 't', 'a', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
fwrite(theReadBuffer, 1, 16, outputFile);
}
void WriteCAFFkukiChunk(FILE * outputFile, void * inCookie, uint32_t inCookieSize)
{
uint8_t thekukiHeaderBuffer[12] = {'k', 'u', 'k', 'i', 0, 0, 0, 0, 0, 0, 0, 0};
thekukiHeaderBuffer[11] = inCookieSize;
fwrite(thekukiHeaderBuffer, 1, 12, outputFile);
fwrite(inCookie, 1, inCookieSize, outputFile);
}
void WriteCAFFChunkSize(FILE * outputFile, int64_t numDataBytes)
{
uint8_t theBuffer[8];
theBuffer[0] = (numDataBytes >> 56) & 0xff;
theBuffer[1] = (numDataBytes >> 48) & 0xff;
theBuffer[2] = (numDataBytes >> 40) & 0xff;
theBuffer[3] = (numDataBytes >> 32) & 0xff;
theBuffer[4] = (numDataBytes >> 24) & 0xff;
theBuffer[5] = (numDataBytes >> 16) & 0xff;
theBuffer[6] = (numDataBytes >> 8) & 0xff;
theBuffer[7] = numDataBytes & 0xff;
fwrite(theBuffer, 1, 8, outputFile);
}
void WriteCAFFchanChunk(FILE * outputFile, uint32_t inChannelTag)
{
uint8_t theBuffer[24] = {'c', 'h', 'a', 'n', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
theBuffer[11] = sizeof(ALACAudioChannelLayout);
theBuffer[12] = inChannelTag >> 24;
theBuffer[13] = (inChannelTag >> 16) & 0xff;
theBuffer[14] = (inChannelTag >> 8) & 0xff;
theBuffer[15] = inChannelTag & 0xff;
fwrite(theBuffer, 1, 24, outputFile);
}
void WriteCAFFfreeChunk(FILE * outputFile, uint32_t theSize)
{
uint8_t theBuffer[12] = {'f', 'r', 'e', 'e', 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t i = 0;
uint32_t theAdjustedSize = theSize - sizeof(port_CAFChunkHeader);
if (theSize > theAdjustedSize) // cause we might have wrapped theAdjustedSize
{
theBuffer[8] = theAdjustedSize >> 24;
theBuffer[9] = (theAdjustedSize >> 16) & 0xff;
theBuffer[10] = (theAdjustedSize >> 8) & 0xff;
theBuffer[11] = theAdjustedSize & 0xff;
fwrite(theBuffer, 1, 12, outputFile);
for (i = 0; i < theAdjustedSize; ++i)
{
fwrite(&(theBuffer[4]), 1, 1, outputFile);
}
}
}
void WriteCAFFpaktChunkHeader(FILE * outputFile, port_CAFPacketTableHeader * thePacketTableHeader, uint32_t thePacketTableSize)
{
uint8_t theBuffer[12];
// Endian swap!
thePacketTableHeader->mNumberPackets = Swap64NtoB(thePacketTableHeader->mNumberPackets);
thePacketTableHeader->mNumberValidFrames = Swap64NtoB(thePacketTableHeader->mNumberValidFrames);
thePacketTableHeader->mPrimingFrames = Swap32NtoB(thePacketTableHeader->mPrimingFrames);
thePacketTableHeader->mRemainderFrames = Swap32NtoB(thePacketTableHeader->mRemainderFrames);
// write out the pakt chunk -- big endian!
theBuffer[0] = 'p';
theBuffer[1] = 'a';
theBuffer[2] = 'k';
theBuffer[3] = 't';
theBuffer[4] = 0;
theBuffer[5] = 0;
theBuffer[6] = 0;
theBuffer[7] = 0;
theBuffer[8] = thePacketTableSize >> 24;
theBuffer[9] = (thePacketTableSize >> 16) & 0xff;
theBuffer[10] = (thePacketTableSize >> 8) & 0xff;
theBuffer[11] = thePacketTableSize & 0xff;
fwrite(theBuffer, 1, 12, outputFile);
fwrite(thePacketTableHeader, 1, kMinCAFFPacketTableHeaderSize, outputFile);
}
void GetBERInteger(int32_t theOriginalValue, uint8_t * theBuffer, int32_t * theBERSize)
{
if ((theOriginalValue & 0x7f) == theOriginalValue)
{
*theBERSize = 1;
theBuffer[0] = theOriginalValue;
}
else if ((theOriginalValue & 0x3fff) == theOriginalValue)
{
*theBERSize = 2;
theBuffer[0] = theOriginalValue >> 7;
theBuffer[0] |= 0x80;
theBuffer[1] = theOriginalValue & 0x7f;
}
else if ((theOriginalValue & 0x1fffff) == theOriginalValue)
{
*theBERSize = 3;
theBuffer[0] = theOriginalValue >> 14;
theBuffer[0] |= 0x80;
theBuffer[1] = (theOriginalValue >> 7) & 0x7f;
theBuffer[1] |= 0x80;
theBuffer[2] = theOriginalValue & 0x7f;
}
else if ((theOriginalValue & 0x0fffffff) == theOriginalValue)
{
*theBERSize = 4;
theBuffer[0] = theOriginalValue >> 21;
theBuffer[0] |= 0x80;
theBuffer[1] = (theOriginalValue >> 14) & 0x7f;
theBuffer[1] |= 0x80;
theBuffer[2] = (theOriginalValue >> 7) & 0x7f;
theBuffer[2] |= 0x80;
theBuffer[3] = theOriginalValue & 0x7f;
}
else
{
*theBERSize = 5;
theBuffer[0] = theOriginalValue >> 28;
theBuffer[0] |= 0x80;
theBuffer[1] = (theOriginalValue >> 21) & 0x7f;
theBuffer[1] |= 0x80;
theBuffer[2] = (theOriginalValue >> 14) & 0x7f;
theBuffer[2] |= 0x80;
theBuffer[3] = (theOriginalValue >> 7) & 0x7f;
theBuffer[3] |= 0x80;
theBuffer[4] = theOriginalValue & 0x7f;
}
}
uint32_t ReadBERInteger(uint8_t * theInputBuffer, int32_t * ioNumBytes)
{
uint32_t theAnswer = 0;
uint8_t theData;
int32_t size = 0;
do
{
theData = theInputBuffer[size];
theAnswer = (theAnswer << 7) | (theData & 0x7F);
if (++size > 5)
{
size = 0xFFFFFFFF;
return 0;
}
}
while(((theData & 0x80) != 0) && (size <= *ioNumBytes));
*ioNumBytes = size;
return theAnswer;
}
int32_t BuildBasePacketTable(AudioFormatDescription theInputFormat, int32_t inputDataSize, int32_t * theMaxPacketTableSize, port_CAFPacketTableHeader * thePacketTableHeader)
{
int32_t theMaxPacketSize = 0, theByteSizeTableEntry = 0;
// fill out the header
thePacketTableHeader->mNumberValidFrames = inputDataSize/((theInputFormat.mBitsPerChannel >> 3) * theInputFormat.mChannelsPerFrame);
thePacketTableHeader->mNumberPackets = thePacketTableHeader->mNumberValidFrames/kALACDefaultFramesPerPacket;
thePacketTableHeader->mPrimingFrames = 0;
thePacketTableHeader->mRemainderFrames = thePacketTableHeader->mNumberValidFrames - thePacketTableHeader->mNumberPackets * kALACDefaultFramesPerPacket;
thePacketTableHeader->mRemainderFrames = kALACDefaultFramesPerPacket - thePacketTableHeader->mRemainderFrames;
if (thePacketTableHeader->mRemainderFrames) thePacketTableHeader->mNumberPackets += 1;
// Ok, we have to assume the worst case scenario for packet sizes
theMaxPacketSize = (theInputFormat.mBitsPerChannel >> 3) * theInputFormat.mChannelsPerFrame * kALACDefaultFramesPerPacket + kALACMaxEscapeHeaderBytes;
if (theMaxPacketSize < 16384)
{
theByteSizeTableEntry = 2;
}
else
{
theByteSizeTableEntry = 3;
}
*theMaxPacketTableSize = theByteSizeTableEntry * thePacketTableHeader->mNumberPackets;
return 0;
}
uint32_t GetMagicCookieSizeFromCAFFkuki(FILE * inputFile)
{
// returns to the current absolute position within the file
int32_t currentPosition = ftell(inputFile); // record the current position
uint8_t theReadBuffer[sizeof(ALACSpecificConfig)];
uint32_t chunkType = 0, chunkSize = 0;
bool done = false;
int32_t bytesRead = sizeof(port_CAFFileHeader);
uint32_t theCookieSize = 0;
fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
while (!done && bytesRead > 0) // no file size here
{
bytesRead = fread(theReadBuffer, 1, 12, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch(chunkType)
{
case 'kuki':
{
theCookieSize = theReadBuffer[11];
done = true;
break;
}
default:
chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
fseek(inputFile, currentPosition, SEEK_SET); // start at 0
if (!done) return -1;
return theCookieSize;
}
// gets the kuki chunk from a caff file
int32_t GetMagicCookieFromCAFFkuki(FILE * inputFile, uint8_t * outMagicCookie, uint32_t * ioMagicCookieSize)
{
// returns to the current absolute position within the file
int32_t currentPosition = ftell(inputFile); // record the current position
uint8_t theReadBuffer[12];
uint32_t chunkType = 0, chunkSize = 0;
bool done = false, cookieFound = false;
int32_t bytesRead = sizeof(port_CAFFileHeader);
uint32_t theStoredCookieSize = 0;
fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
while (!done && bytesRead > 0) // no file size here
{
bytesRead = fread(theReadBuffer, 1, 12, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch(chunkType)
{
case 'kuki':
{
theStoredCookieSize = theReadBuffer[11];
if (*ioMagicCookieSize >= theStoredCookieSize)
{
fread(outMagicCookie, 1, theStoredCookieSize, inputFile);
*ioMagicCookieSize = theStoredCookieSize;
cookieFound = true;
}
else
{
*ioMagicCookieSize = 0;
}
done = true;
break;
}
default:
chunkSize = ((int32_t)(theReadBuffer[8]) << 24) + ((int32_t)(theReadBuffer[9]) << 16) + ((int32_t)(theReadBuffer[10]) << 8) + theReadBuffer[11];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
fseek(inputFile, currentPosition, SEEK_SET); // start at 0
if (!done || !cookieFound) return -1;
return 0;
}
bool FindCAFFDataStart(FILE * inputFile, int32_t * dataPos, int32_t * dataSize)
{
bool done = false;
int32_t bytesRead = 8;
uint32_t chunkType = 0, chunkSize = 0;
uint8_t theBuffer[12];
fseek(inputFile, bytesRead, SEEK_SET); // start at 8!
while (!done && bytesRead > 0) // no file size here
{
bytesRead = fread(theBuffer, 1, 12, inputFile);
chunkType = ((int32_t)(theBuffer[0]) << 24) + ((int32_t)(theBuffer[1]) << 16) + ((int32_t)(theBuffer[2]) << 8) + theBuffer[3];
switch(chunkType)
{
case 'data':
*dataPos = ftell(inputFile) + sizeof(uint32_t); // skip the edits
// big endian size
*dataSize = ((int32_t)(theBuffer[8]) << 24) + ((int32_t)(theBuffer[9]) << 16) + ((int32_t)(theBuffer[10]) << 8) + theBuffer[11];
*dataSize -= 4; // the edits are included in the size
done = true;
break;
default:
chunkSize = ((int32_t)(theBuffer[8]) << 24) + ((int32_t)(theBuffer[9]) << 16) + ((int32_t)(theBuffer[10]) << 8) + theBuffer[11];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
return done;
}
bool GetCAFFdescFormat(FILE * inputFile, AudioFormatDescription * theInputFormat)
{
bool done = false;
uint32_t theChunkSize = 0, theChunkType = 0;
uint8_t theReadBuffer[32];
fseek(inputFile, 4, SEEK_CUR); // skip 4 bytes
while (!done)
{
fread(theReadBuffer, 1, 4, inputFile);
theChunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch (theChunkType)
{
case 'desc':
fseek(inputFile, 8, SEEK_CUR); // skip 8 bytes
fread(theReadBuffer, 1, sizeof(port_CAFAudioDescription), inputFile);
theInputFormat->mFormatID = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFormatID);
theInputFormat->mChannelsPerFrame = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mChannelsPerFrame);
theInputFormat->mSampleRate = SwapFloat64BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mSampleRate);
theInputFormat->mBitsPerChannel = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mBitsPerChannel);
theInputFormat->mFormatFlags = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFormatFlags);
theInputFormat->mBytesPerPacket = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mBytesPerPacket);
if (theInputFormat->mFormatID == kALACFormatAppleLossless)
{
theInputFormat->mBytesPerFrame = 0;
}
else
{
theInputFormat->mBytesPerFrame = theInputFormat->mBytesPerPacket;
if ((theInputFormat->mFormatFlags & 0x02) == 0x02)
{
theInputFormat->mFormatFlags &= 0xfffffffc;
}
else
{
theInputFormat->mFormatFlags |= 0x02;
}
}
theInputFormat->mFramesPerPacket = Swap32BtoN(((port_CAFAudioDescription *)(theReadBuffer))->mFramesPerPacket);
theInputFormat->mReserved = 0;
done = true;
break;
default:
// read the size and skip
fread(theReadBuffer, 1, 8, inputFile);
theChunkSize = ((int32_t)(theReadBuffer[4]) << 24) + ((int32_t)(theReadBuffer[5]) << 16) + ((int32_t)(theReadBuffer[6]) << 8) + theReadBuffer[7];
fseek(inputFile, theChunkSize, SEEK_CUR);
break;
}
}
return done;
}

View File

@@ -0,0 +1,209 @@
/*
Copyright © 2011 Apple Inc. All rights reserved.
IMPORTANT: This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//
// CAFFileALAC.h
// based CAFFile.h in the CoreAudio headers, ALAC specific
//
// Copyright 2011 Apple Inc. All rights reserved.
//
#ifndef _CAFFilePortable_h
#define _CAFFilePortable_h
#if TARGET_OS_WIN32
#define ATTRIBUTE_PACKED
#pragma pack(push, 1)
#else
#define ATTRIBUTE_PACKED __attribute__((__packed__))
#endif
#include "ALACAudioTypes.h"
#define kMinCAFFPacketTableHeaderSize 24
typedef uint32_t CAFFChannelLayoutTag;
// These are subset of the channel layout tags listed in CoreAudioTypes.h
// ALAC and caff both use the same tag values
enum
{
kCAFFChannelLayoutTag_Mono = (100<<16) | 1, // C
kCAFFChannelLayoutTag_Stereo = (101<<16) | 2, // L R
kCAFFChannelLayoutTag_MPEG_3_0_B = (113<<16) | 3, // C L R
kCAFFChannelLayoutTag_MPEG_4_0_B = (116<<16) | 4, // C L R Cs
kCAFFChannelLayoutTag_MPEG_5_0_D = (120<<16) | 5, // C L R Ls Rs
kCAFFChannelLayoutTag_MPEG_5_1_D = (124<<16) | 6, // C L R Ls Rs LFE
kCAFFChannelLayoutTag_AAC_6_1 = (142<<16) | 7, // C L R Ls Rs Cs LFE
kCAFFChannelLayoutTag_MPEG_7_1_B = (127<<16) | 8 // C Lc Rc L R Ls Rs LFE
};
// ALAC currently only utilizes these channels layouts. CAFF supports all those listed in
// CoreAudioTypes.h.
static const CAFFChannelLayoutTag CAFFChannelLayoutTags[kALACMaxChannels] =
{
kCAFFChannelLayoutTag_Mono, // C
kCAFFChannelLayoutTag_Stereo, // L R
kCAFFChannelLayoutTag_MPEG_3_0_B, // C L R
kCAFFChannelLayoutTag_MPEG_4_0_B, // C L R Cs
kCAFFChannelLayoutTag_MPEG_5_0_D, // C L R Ls Rs
kCAFFChannelLayoutTag_MPEG_5_1_D, // C L R Ls Rs LFE
kCAFFChannelLayoutTag_AAC_6_1, // C L R Ls Rs Cs LFE
kCAFFChannelLayoutTag_MPEG_7_1_B // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
};
// In a CAF File all of these types' byte order is big endian.
// When reading or writing these values the program will need to flip byte order to native endian
// CAF File Header
enum {
k_port__port_CAF_FileType = 'caff',
k_port_CAF_FileVersion_Initial = 1
};
// CAF Chunk Types
enum {
k_port_CAF_StreamDescriptionChunkID = 'desc',
k_port_CAF_AudioDataChunkID = 'data',
k_port_CAF_ChannelLayoutChunkID = 'chan',
k_port_CAF_MagicCookieID = 'kuki',
k_port_CAF_PacketTableChunkID = 'pakt',
k_port_CAF_FreeTableChunkID = 'free'
};
struct port_CAFFileHeader
{
uint32_t mFileType; // 'caff'
uint16_t mFileVersion; //initial revision set to 1
uint16_t mFileFlags; //initial revision set to 0
} ATTRIBUTE_PACKED;
typedef struct CAFFileHeader CAFFileHeader;
struct port_CAFChunkHeader
{
uint32_t mChunkType; // four char code
int64_t mChunkSize; // size in bytes of the chunk data (not including this header).
// mChunkSize is int64_t not uint64_t because negative values for
// the data size can have a special meaning
} ATTRIBUTE_PACKED;
typedef struct port_CAFChunkHeader port_CAFChunkHeader;
// Every file MUST have this chunk. It MUST be the first chunk in the file
struct port_CAFAudioDescription
{
double mSampleRate;
uint32_t mFormatID;
uint32_t mFormatFlags;
uint32_t mBytesPerPacket;
uint32_t mFramesPerPacket;
uint32_t mChannelsPerFrame;
uint32_t mBitsPerChannel;
} ATTRIBUTE_PACKED;
typedef struct port_CAFAudioDescription port_CAFAudioDescription;
// these are the flags if the format ID is 'lpcm'
// <CoreAudio/CoreAudioTypes.h> declares some of the format constants
// that can be used as Data Formats in a CAF file
enum
{
k_port_CAFLinearPCMFormatFlagIsFloat = (1L << 0),
k_port_CAFLinearPCMFormatFlagIsLittleEndian = (1L << 1)
};
// 'chan' Optional chunk.
// struct AudioChannelLayout as defined in CoreAudioTypes.h.
// 'free'
// this is a padding chunk for reserving space in the file. content is meaningless.
// 'kuki'
// this is the magic cookie chunk. bag of bytes.
// 'data' Every file MUST have this chunk.
// actual audio data can be any format as described by the 'asbd' chunk.
// if mChunkSize is < 0 then this is the last chunk in the file and the actual length
// should be determined from the file size.
// The motivation for this is to allow writing the files without seeking to update size fields after every
// write in order to keep the file legal.
// The program can put a -1 in the mChunkSize field and
// update it only once at the end of recording.
// If the program were to crash during recording then the file is still well defined.
// 'pakt' Required if either/or mBytesPerPacket or mFramesPerPacket in the Format Description are zero
// For formats that are packetized and have variable sized packets.
// The table is stored as an array of one or two variable length integers.
// (a) size in bytes of the data of a given packet.
// (b) number of frames in a given packet.
// These sizes are encoded as variable length integers
// The packet description entries are either one or two values depending on the format.
// There are three possibilities
// (1)
// If the format has variable bytes per packets (desc.mBytesPerPacket == 0) and constant frames per packet
// (desc.mFramesPerPacket != 0) then the packet table contains single entries representing the bytes in a given packet
// (2)
// If the format is a constant bit rate (desc.mBytesPerPacket != 0) but variable frames per packet
// (desc.mFramesPerPacket == 0) then the packet table entries contains single entries
// representing the number of frames in a given packet
// (3)
// If the format has variable frames per packet (asbd.mFramesPerPacket == 0) and variable bytes per packet
// (desc.mBytesPerPacket == 0) then the packet table entries are a duple of two values. The first value
// is the number of bytes in a given packet, the second value is the number of frames in a given packet
struct port_CAFPacketTableHeader
{
int64_t mNumberPackets;
int64_t mNumberValidFrames;
int32_t mPrimingFrames;
int32_t mRemainderFrames;
uint8_t mPacketDescriptions[1]; // this is a variable length array of mNumberPackets elements
} ATTRIBUTE_PACKED;
typedef struct port_CAFPacketTableHeader port_CAFPacketTableHeader;
struct port_CAFDataChunk
{
uint32_t mEditCount;
uint8_t mData[1]; // this is a variable length data field based off the size of the data chunk
} ATTRIBUTE_PACKED;
typedef struct port_CAFDataChunk port_CAFDataChunk;
// prototypes
int32_t FindCAFFPacketTableStart(FILE * inputFile, int32_t * paktPos, int32_t * paktSize);
void WriteCAFFcaffChunk(FILE * outputFile);
void WriteCAFFdescChunk(FILE * outputFile, AudioFormatDescription theOutputFormat);
void WriteCAFFdataChunk(FILE * outputFile);
void WriteCAFFkukiChunk(FILE * outputFile, void * inCookie, uint32_t inCookieSize);
void WriteCAFFChunkSize(FILE * outputFile, int64_t numDataBytes);
void WriteCAFFchanChunk(FILE * outputFile, uint32_t inChannelTag);
void WriteCAFFfreeChunk(FILE * outputFile, uint32_t theSize);
void WriteCAFFpaktChunkHeader(FILE * outputFile, port_CAFPacketTableHeader * thePacketTableHeader, uint32_t thePacketTableSize);
void GetBERInteger(int32_t theOriginalValue, uint8_t * theBuffer, int32_t * theBERSize);
uint32_t ReadBERInteger(uint8_t * theInputBuffer, int32_t * ioNumBytes);
int32_t BuildBasePacketTable(AudioFormatDescription theInputFormat, int32_t inputDataSize, int32_t * thePacketTableSize, port_CAFPacketTableHeader * thePacketTableHeader);
uint32_t GetMagicCookieSizeFromCAFFkuki(FILE * inputFile);
int32_t GetMagicCookieFromCAFFkuki(FILE * inputFile, uint8_t * outMagicCookie, uint32_t * ioMagicCookieSize);
bool FindCAFFDataStart(FILE * inputFile, int32_t * dataPos, int32_t * dataSize);
bool GetCAFFdescFormat(FILE * inputFile, AudioFormatDescription * theInputFormat);
#if TARGET_OS_WIN32
#pragma pack(pop)
#endif
////////////////////////////////////////////////////////////////////////////////////////////////
#endif

View File

@@ -0,0 +1,784 @@
/*
Copyright © 2011 Apple Inc. All rights reserved.
IMPORTANT: This Apple software is supplied to you by Apple Inc. (“Apple”) in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this Apple software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apples copyrights in this original Apple software (the “Apple Software”), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software. Neither the name, trademarks, service marks or logos of Apple Inc. may be used to endorse or promote products derived from the Apple Software without specific prior written permission from Apple. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Apple herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* main.cpp
*
* Converts pcm data contained in a .wav or .caf file into Apple Lossless (ALAC) put into a .caf file
* or converts ALAC data from a .caf file into pcm data and put into a .wav or .caf file
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// these are headers for the ALAC encoder and decoder
#include "ALACEncoder.h"
#include "ALACDecoder.h"
#include "ALACBitUtilities.h"
// these are utility headers for this sample code
#include "CAFFileALAC.h"
#include "EndianPortable.h"
#define kMaxBERSize 5
#define kCAFFdataChunkEditsSize 4
#define kWAVERIFFChunkSize 12
#define kWAVEfmtChunkSize 24
#define kWAVEdataChunkHeaderSize 8
#define VERBOSE 0
// Helper functions
int32_t GetInputFormat(FILE * inputFile, AudioFormatDescription * theInputFormat, uint32_t * theFileType);
int32_t SetOutputFormat(AudioFormatDescription theInputFormat, AudioFormatDescription * theOutputFormat);
int32_t FindDataStart(FILE * inputFile, uint32_t inputFileType, int32_t * dataPos, int32_t * dataSize);
int32_t EncodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize);
int32_t DecodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize, uint32_t outputFileType);
void GetOutputFileType(char * outputFileName, uint32_t * outputFileType);
ALACChannelLayoutTag GetALACChannelLayoutTag(uint32_t inChannelsPerFrame);
// Some crude WAVE writing tools
void WriteWAVERIFFChunk(FILE * outputFile);
void WriteWAVEfmtChunk(FILE * outputFile, AudioFormatDescription theOutputFormat);
void WriteWAVEdataChunk(FILE * outputFile);
void WriteWAVEChunkSize(FILE * outputFile, uint32_t numDataBytes);
// Adapted from CoreAudioTypes.h
enum
{
kTestFormatFlag_16BitSourceData = 1,
kTestFormatFlag_20BitSourceData = 2,
kTestFormatFlag_24BitSourceData = 3,
kTestFormatFlag_32BitSourceData = 4
};
int32_t main (int32_t argc, char * argv[])
{
char * inputFileName = argv[1];
char * outputFileName = argv[2];
FILE * inputFile = NULL;
FILE * outputFile = NULL;
bool malformed = argc < 2;
// Parse the commandline and open the necessary files
for (int32_t i = 1; i < argc; ++i)
{
if (strcmp (argv[i], "-h") == 0)
{
malformed = true;
}
else
{
if (argv[i][0] == '-')
{
printf ("unknown option: %s\n", argv[i]);
malformed = true;
}
else
{
if (inputFile == NULL) inputFile = fopen (inputFileName, "rb"); // the b is necessary for Windows -- ignored by Unix
if(inputFile == NULL)
{
fprintf(stderr," Cannot open file \"%s\"\n", inputFileName);
exit (1);
}
if (outputFile == NULL) outputFile = fopen (outputFileName, "w+b"); // the b is necessary for Windows -- ignored by Unix
if(outputFile == NULL)
{
fprintf(stderr," Cannot open file \"%s\"\n", outputFileName);
exit (1);
}
}
}
if (malformed)
{
break;
}
}
if (!malformed)
{
printf("Input file: %s\n", inputFileName);
printf("Output file: %s\n", outputFileName);
// So at this point we have the input and output files open. Need to determine what we're dealing with
int32_t theError = 0;
AudioFormatDescription inputFormat;
AudioFormatDescription outputFormat;
int32_t inputDataPos = 0, inputDataSize = 0;
uint32_t inputFileType = 0; // 'caff' or 'WAVE'
uint32_t outputFileType = 0; // 'caff' or 'WAVE'
theError = GetInputFormat(inputFile, &inputFormat, &inputFileType);
if (theError)
{
fprintf(stderr," Cannot determine what format file \"%s\" is\n", inputFileName);
exit (1);
}
if (inputFileType != 'WAVE' && inputFileType != 'caff')
{
fprintf(stderr," File \"%s\" is of an unsupported type\n", outputFileName);
exit (1);
}
if (inputFormat.mFormatID != kALACFormatAppleLossless && inputFormat.mFormatID != kALACFormatLinearPCM)
{
fprintf(stderr," File \"%s\'s\" data format is of an unsupported type\n", outputFileName);
exit (1);
}
SetOutputFormat(inputFormat, &outputFormat);
if (theError)
{
fprintf(stderr," Cannot determine what format file \"%s\" is\n", outputFileName);
exit (1);
}
FindDataStart(inputFile, inputFileType, &inputDataPos, &inputDataSize);
fseek(inputFile, inputDataPos, SEEK_SET);
// We know where we are and we know what we're doing
if (outputFormat.mFormatID == kALACFormatAppleLossless)
{
// encoding
EncodeALAC(inputFile, outputFile, inputFormat, outputFormat, inputDataSize);
}
else
{
// decoding
GetOutputFileType(outputFileName, &outputFileType);
if (outputFileType == 'WAVE' && outputFormat.mChannelsPerFrame > 2)
{
// we don't support WAVE because we don't want to reinterleave on output
fprintf(stderr," Cannot decode more than two channels to WAVE\n");
exit (1);
}
DecodeALAC(inputFile, outputFile, inputFormat, outputFormat, inputDataSize, outputFileType);
}
}
if (malformed) {
printf ("Usage:\n");
printf ("Encode:\n");
printf (" alacconvert <input wav or caf file> <output caf file>\n");
printf ("Decode:\n");
printf (" alacconvert <input caf file> <output wav or caf file>\n");
printf ("\n");
return 1;
}
if (inputFile) fclose(inputFile);
if (outputFile) fclose(outputFile);
return 0;
}
int32_t GetInputFormat(FILE * inputFile, AudioFormatDescription * theInputFormat, uint32_t * theFileType)
{
// assumes the file is open
uint8_t theReadBuffer[20];
bool done = false;
uint32_t chunkType = 0;
fread(theReadBuffer, 1, 4, inputFile);
if (theReadBuffer[0] == 'c' && theReadBuffer[1] == 'a' && theReadBuffer[2] == 'f' & theReadBuffer[3] == 'f')
{
// It's a caff file!
*theFileType = 'caff';
// We support pcm data for encode and alac data for decode
done = GetCAFFdescFormat(inputFile, theInputFormat);
}
else if (theReadBuffer[0] == 'R' && theReadBuffer[1] == 'I' && theReadBuffer[2] == 'F' & theReadBuffer[3] == 'F')
{
fread(theReadBuffer, 1, 8, inputFile);
if (theReadBuffer[4] == 'W' && theReadBuffer[5] == 'A' && theReadBuffer[6] == 'V' & theReadBuffer[7] == 'E')
{
// It's a WAVE file!
*theFileType = 'WAVE';
// We only support pcm data
while (!done)
{
uint32_t theChunkSize = 0, theSampleRate = 0;
fread(theReadBuffer, 1, 4, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch (chunkType)
{
case 'fmt ':
fread(theReadBuffer, 1, 20, inputFile);
// Remember campers we're in little endian land
if (theReadBuffer[4] != 1 || theReadBuffer[5] != 0)
{
// we only support PCM
*theFileType = 0; // clear it
return -1;
}
theInputFormat->mFormatID = kALACFormatLinearPCM;
theInputFormat->mChannelsPerFrame = theReadBuffer[6];
theSampleRate = ((int32_t)(theReadBuffer[11]) << 24) + ((int32_t)(theReadBuffer[10]) << 16) + ((int32_t)(theReadBuffer[9]) << 8) + theReadBuffer[8];
theInputFormat->mSampleRate = theSampleRate;
theInputFormat->mBitsPerChannel = theReadBuffer[18];
theInputFormat->mFormatFlags = kALACFormatFlagIsSignedInteger | kALACFormatFlagIsPacked; // always little endian
theInputFormat->mBytesPerPacket = theInputFormat->mBytesPerFrame = (theInputFormat->mBitsPerChannel >> 3) * theInputFormat->mChannelsPerFrame;
theInputFormat->mFramesPerPacket = 1;
theInputFormat->mReserved = 0;
done = true;
break;
default:
// read the size and skip
fread(theReadBuffer, 1, 4, inputFile);
theChunkSize = ((int32_t)(theReadBuffer[3]) << 24) + ((int32_t)(theReadBuffer[2]) << 16) + ((int32_t)(theReadBuffer[1]) << 8) + theReadBuffer[0];
fseek(inputFile, theChunkSize, SEEK_CUR);
break;
}
}
}
else
{
*theFileType = 0; // clear it
return -1;
}
}
else
{
*theFileType = 0; // clear it
return -1;
}
if (!done) return -1;
return 0;
}
int32_t SetOutputFormat(AudioFormatDescription theInputFormat, AudioFormatDescription * theOutputFormat)
{
if (theInputFormat.mFormatID == kALACFormatLinearPCM)
{
// encoding
theOutputFormat->mFormatID = kALACFormatAppleLossless;
theOutputFormat->mSampleRate = theInputFormat.mSampleRate;
switch(theInputFormat.mBitsPerChannel)
{
case 16:
theOutputFormat->mFormatFlags = kTestFormatFlag_16BitSourceData;
break;
case 20:
theOutputFormat->mFormatFlags = kTestFormatFlag_20BitSourceData;
break;
case 24:
theOutputFormat->mFormatFlags = kTestFormatFlag_24BitSourceData;
break;
case 32:
theOutputFormat->mFormatFlags = kTestFormatFlag_32BitSourceData;
break;
default:
return -1;
break;
}
theOutputFormat->mFramesPerPacket = kALACDefaultFramesPerPacket;
theOutputFormat->mChannelsPerFrame = theInputFormat.mChannelsPerFrame;
// mBytesPerPacket == 0 because we are VBR
// mBytesPerFrame and mBitsPerChannel == 0 because there are no discernable bits assigned to a particular sample
// mReserved is always 0
theOutputFormat->mBytesPerPacket = theOutputFormat->mBytesPerFrame = theOutputFormat->mBitsPerChannel = theOutputFormat->mReserved = 0;
}
else
{
// decoding
theOutputFormat->mFormatID = kALACFormatLinearPCM;
theOutputFormat->mSampleRate = theInputFormat.mSampleRate;
switch(theInputFormat.mFormatFlags)
{
case kTestFormatFlag_16BitSourceData:
theOutputFormat->mBitsPerChannel = 16;
break;
case kTestFormatFlag_20BitSourceData:
theOutputFormat->mBitsPerChannel = 20;
break;
case kTestFormatFlag_24BitSourceData:
theOutputFormat->mBitsPerChannel = 24;
break;
case kTestFormatFlag_32BitSourceData:
theOutputFormat->mBitsPerChannel = 32;
break;
default:
return -1;
break;
}
theOutputFormat->mFramesPerPacket = 1;
theOutputFormat->mChannelsPerFrame = theInputFormat.mChannelsPerFrame;
theOutputFormat->mBytesPerPacket = theOutputFormat->mBytesPerFrame = theOutputFormat->mBitsPerChannel != 20 ? theInputFormat.mChannelsPerFrame * ((theOutputFormat->mBitsPerChannel) >> 3) : (int32_t)(theInputFormat.mChannelsPerFrame * 2.5 + .5);
theOutputFormat->mFormatFlags = kALACFormatFlagsNativeEndian;
theOutputFormat->mReserved = 0;
}
return 0;
}
int32_t FindDataStart(FILE * inputFile, uint32_t inputFileType, int32_t * dataPos, int32_t * dataSize)
{
// returns the absolute position within the file
int32_t currentPosition = ftell(inputFile); // record the current position
uint8_t theReadBuffer[12];
uint32_t chunkType = 0, fileSize = 0, chunkSize = 0;
bool done = false;
switch (inputFileType)
{
case 'WAVE':
fseek(inputFile, 0, SEEK_SET); // start at 0
fread(theReadBuffer, 1, 8, inputFile);
fileSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
fseek(inputFile, 12, SEEK_SET); // start at 12!
while (!done && ((uint32_t)(ftell(inputFile)) < fileSize))
{
fread(theReadBuffer, 1, 8, inputFile);
chunkType = ((int32_t)(theReadBuffer[0]) << 24) + ((int32_t)(theReadBuffer[1]) << 16) + ((int32_t)(theReadBuffer[2]) << 8) + theReadBuffer[3];
switch(chunkType)
{
case 'data':
*dataPos = ftell(inputFile);
// little endian size
*dataSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
done = true;
break;
default:
chunkSize = ((int32_t)(theReadBuffer[7]) << 24) + ((int32_t)(theReadBuffer[6]) << 16) + ((int32_t)(theReadBuffer[5]) << 8) + theReadBuffer[4];
fseek(inputFile, chunkSize, SEEK_CUR);
break;
}
}
break;
case 'caff':
done = FindCAFFDataStart(inputFile, dataPos, dataSize);
break;
}
fseek(inputFile, currentPosition, SEEK_SET); // start at 0
if (!done) return -1;
return 0;
}
int32_t EncodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize)
{
int32_t theInputPacketBytes = theInputFormat.mChannelsPerFrame * (theInputFormat.mBitsPerChannel >> 3) * theOutputFormat.mFramesPerPacket;
int32_t theOutputPacketBytes = theInputPacketBytes + kALACMaxEscapeHeaderBytes;
int32_t thePacketTableSize = 0, packetTablePos = 0, dataPos = 0, dataSizePos = 0, theBERSize = 0, packetTableSizePos;
uint8_t * theReadBuffer = (uint8_t *)calloc(theInputPacketBytes, 1);
uint8_t * theWriteBuffer = (uint8_t *)calloc(theOutputPacketBytes, 1);
int32_t numBytes = 0;
uint32_t packetTableBytesLeft = 0;
int64_t numDataBytes = 0;
port_CAFPacketTableHeader thePacketTableHeader;
int32_t inputDataBytesRemaining = inputDataSize;
uint8_t * theMagicCookie = NULL;
uint32_t theMagicCookieSize = 0;
ALACEncoder * theEncoder = new ALACEncoder;
theEncoder->SetFrameSize(theOutputFormat.mFramesPerPacket);
theEncoder->InitializeEncoder(theOutputFormat);
// we only write out the caff header, the 'desc' chunk. the 'kuki' chunk, the 'pakt' chunk and the 'data' chunk
// write out the caff header
WriteCAFFcaffChunk(outputFile);
// write out the desc chunk
WriteCAFFdescChunk(outputFile, theOutputFormat);
// get the magic cookie
theMagicCookieSize = theEncoder->GetMagicCookieSize(theOutputFormat.mChannelsPerFrame);
theMagicCookie = (uint8_t *)calloc(theMagicCookieSize, 1);
theEncoder->GetMagicCookie(theMagicCookie, &theMagicCookieSize);
// write out the kuki chunk
WriteCAFFkukiChunk(outputFile, theMagicCookie, theMagicCookieSize);
free(theMagicCookie);
// We might be multi channel
if (theOutputFormat.mChannelsPerFrame > 2)
{
WriteCAFFchanChunk(outputFile, GetALACChannelLayoutTag(theOutputFormat.mChannelsPerFrame));
}
// Figure out the maximum size and build the base pakt header
BuildBasePacketTable(theInputFormat, inputDataSize, &thePacketTableSize, &thePacketTableHeader);
packetTableBytesLeft = thePacketTableSize;
// This could be substantially larger than either the read or write buffer, so allocate a block of memory here
// all we're going to do is copy it to the file
uint8_t * thePacketTableEntries = (uint8_t *)calloc (thePacketTableSize, 1);
/* move */
thePacketTableSize += kMinCAFFPacketTableHeaderSize;
WriteCAFFpaktChunkHeader(outputFile, &thePacketTableHeader, thePacketTableSize);
packetTableSizePos = packetTablePos = ftell(outputFile);
packetTableSizePos -= (sizeof(int64_t) + kMinCAFFPacketTableHeaderSize);
thePacketTableSize -= kMinCAFFPacketTableHeaderSize;
fwrite (thePacketTableEntries, 1, thePacketTableSize, outputFile);
free(thePacketTableEntries);
// We'll write out the data chunk next. The 'data' size will start past the 'data' chunk identifier
dataSizePos = ftell(outputFile) + sizeof(uint32_t);
// Finally, write out the data chunk
WriteCAFFdataChunk(outputFile);
dataPos = ftell(outputFile);
while (theInputPacketBytes <= inputDataBytesRemaining)
{
numBytes = fread(theReadBuffer, 1, theInputPacketBytes, inputFile);
#if VERBOSE
printf ("Read %i bytes\n", numBytes);
#endif
inputDataBytesRemaining -= numBytes;
if ((theInputFormat.mFormatFlags & 0x02) != kALACFormatFlagsNativeEndian)
{
#if VERBOSE
printf ("Byte Swapping!\n");
#endif
if (theInputFormat.mBitsPerChannel == 16)
{
uint16_t * theShort = (uint16_t *)theReadBuffer;
for (int32_t i = 0; i < (numBytes >> 1); ++i)
{
Swap16(&(theShort[i]));
}
}
else if (theInputFormat.mBitsPerChannel == 32)
{
uint32_t * theLong = (uint32_t *)theReadBuffer;
for (int32_t i = 0; i < (numBytes >> 2); ++i)
{
Swap32(&(theLong[i]));
}
}
else // covers both 20 and 24
{
for (int32_t i = 0; i < numBytes; i += 3)
{
Swap24(&(theReadBuffer[i]));
}
}
}
theEncoder->Encode(theInputFormat, theInputFormat, theReadBuffer, theWriteBuffer, &numBytes);
GetBERInteger(numBytes, theReadBuffer, &theBERSize);
fseek(outputFile, packetTablePos, SEEK_SET);
fwrite(theReadBuffer, 1, theBERSize, outputFile);
packetTablePos += theBERSize;
packetTableBytesLeft -= theBERSize;
fseek(outputFile, dataPos, SEEK_SET);
fwrite(theWriteBuffer, 1, numBytes, outputFile);
dataPos += numBytes;
numDataBytes += numBytes;
#if VERBOSE
printf ("Writing %i bytes\n", numBytes);
#endif
}
// encode the last partial packet
if (inputDataBytesRemaining)
{
numBytes = fread(theReadBuffer, 1, inputDataBytesRemaining, inputFile);
#if VERBOSE
printf ("Last Packet! Read %i bytes\n", numBytes);
#endif
inputDataBytesRemaining -= numBytes;
if ((theInputFormat.mFormatFlags & 0x02) != kALACFormatFlagsNativeEndian)
{
#if VERBOSE
printf ("Byte Swapping!\n");
#endif
if (theInputFormat.mBitsPerChannel == 16)
{
uint16_t * theShort = (uint16_t *)theReadBuffer;
for (int32_t i = 0; i < (numBytes >> 1); ++i)
{
Swap16(&(theShort[i]));
}
}
else if (theInputFormat.mBitsPerChannel == 32)
{
uint32_t * theLong = (uint32_t *)theReadBuffer;
for (int32_t i = 0; i < (numBytes >> 2); ++i)
{
Swap32(&(theLong[i]));
}
}
else // covers both 20 and 24
{
for (int32_t i = 0; i < numBytes; i += 3)
{
Swap24(&(theReadBuffer[i]));
}
}
}
theEncoder->Encode(theInputFormat, theInputFormat, theReadBuffer, theWriteBuffer, &numBytes);
GetBERInteger(numBytes, theReadBuffer, &theBERSize);
fseek(outputFile, packetTablePos, SEEK_SET);
fwrite(theReadBuffer, 1, theBERSize, outputFile);
packetTablePos += theBERSize;
packetTableBytesLeft -= theBERSize;
fseek(outputFile, dataPos, SEEK_SET);
fwrite(theWriteBuffer, 1, numBytes, outputFile);
dataPos += numBytes;
numDataBytes += numBytes;
#if VERBOSE
printf ("Writing %i bytes\n", numBytes);
#endif
}
// cleanup -- if we have a lot of bytes left over in packet table, write a free chunk
if (packetTableBytesLeft > sizeof(port_CAFChunkHeader)) // min size required to write
{
#if VERBOSE
printf ("Writing %i free bytes\n", packetTableBytesLeft);
#endif
fseek(outputFile, packetTablePos, SEEK_SET);
WriteCAFFfreeChunk(outputFile, packetTableBytesLeft);
fseek(outputFile, packetTableSizePos, SEEK_SET);
WriteCAFFChunkSize(outputFile, thePacketTableSize - packetTableBytesLeft + kMinCAFFPacketTableHeaderSize);
}
// write out the data size
fseek(outputFile, dataSizePos, SEEK_SET);
numDataBytes += kCAFFdataChunkEditsSize;
#if VERBOSE
printf ("numDataBytes == %i bytes\n", numDataBytes);
#endif
WriteCAFFChunkSize(outputFile, numDataBytes);
delete theEncoder;
free(theReadBuffer);
free(theWriteBuffer);
return 0;
}
// There's not a whole lot of difference between encode and decode on this level
int32_t DecodeALAC(FILE * inputFile, FILE * outputFile, AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, int32_t inputDataSize, uint32_t outputFileType)
{
int32_t theInputPacketBytes = theInputFormat.mChannelsPerFrame * (theOutputFormat.mBitsPerChannel >> 3) * theInputFormat.mFramesPerPacket + kALACMaxEscapeHeaderBytes;
int32_t theOutputPacketBytes = theInputPacketBytes - kALACMaxEscapeHeaderBytes;
int32_t thePacketTableSize = 0, packetTablePos = 0, outputDataSizePos = 0, inputDataPos = 0;
uint8_t * theReadBuffer = (uint8_t *)calloc(theInputPacketBytes, 1);
uint8_t * theWriteBuffer = (uint8_t *)calloc(theOutputPacketBytes, 1);
int32_t numBytes = 0;
int64_t numDataBytes = 0;
uint32_t numFrames = 0;
BitBuffer theInputBuffer;
uint8_t * theMagicCookie = NULL;
uint32_t theMagicCookieSize = 0;
ALACDecoder * theDecoder = new ALACDecoder;
// We need to get the cookie from the file
theMagicCookieSize = GetMagicCookieSizeFromCAFFkuki(inputFile);
theMagicCookie = (uint8_t *)calloc(theMagicCookieSize, 1);
GetMagicCookieFromCAFFkuki(inputFile, theMagicCookie, &theMagicCookieSize);
// While we don't have a use for this here, if you were using arbitrary channel layouts, you'd need to run the following check:
theDecoder->Init(theMagicCookie, theMagicCookieSize);
free(theMagicCookie);
BitBufferInit(&theInputBuffer, theReadBuffer, theInputPacketBytes);
inputDataPos = ftell(inputFile);
if (outputFileType != 'WAVE')
{
// we only write out the caff header, the 'desc' chunk and the 'data' chunk
// write out the caff header
WriteCAFFcaffChunk(outputFile);
// write out the desc chunk
WriteCAFFdescChunk(outputFile, theOutputFormat);
// We might be multi channel
if (theOutputFormat.mChannelsPerFrame > 2)
{
// we are not rearranging the output data
WriteCAFFchanChunk(outputFile, CAFFChannelLayoutTags[theOutputFormat.mChannelsPerFrame - 1]);
}
// We'll write out the data chunk next. The 'data' size will start past the 'data' chunk identifier
outputDataSizePos = ftell(outputFile) + sizeof(uint32_t);
// Finally, write out the data chunk
WriteCAFFdataChunk(outputFile);
}
else
{
// We're writing a mono or stereo WAVE file
WriteWAVERIFFChunk(outputFile);
WriteWAVEfmtChunk(outputFile, theOutputFormat);
WriteWAVEdataChunk(outputFile);
outputDataSizePos = ftell(outputFile) - sizeof(uint32_t);
}
// We do have to get the packet size from the packet table
FindCAFFPacketTableStart(inputFile, &packetTablePos, &thePacketTableSize);
fseek(inputFile, packetTablePos, SEEK_SET);
numBytes = fread(theReadBuffer, 1, kMaxBERSize, inputFile);
theInputPacketBytes = ReadBERInteger(theReadBuffer, &numBytes);
packetTablePos += numBytes;
fseek(inputFile, inputDataPos, SEEK_SET);
inputDataPos += theInputPacketBytes;
while ((theInputPacketBytes > 0) && ((size_t)theInputPacketBytes == fread(theReadBuffer, 1, theInputPacketBytes, inputFile)))
{
#if VERBOSE
printf ("Read %i bytes\n", theInputPacketBytes);
#endif
theDecoder->Decode(&theInputBuffer, theWriteBuffer, theInputFormat.mFramesPerPacket, theInputFormat.mChannelsPerFrame, &numFrames);
numBytes = numFrames * theOutputFormat.mBytesPerFrame;
#if VERBOSE
printf ("Writing %i bytes\n", numBytes);
#endif
fwrite(theWriteBuffer, 1, numBytes, outputFile);
numDataBytes += numBytes;
fseek(inputFile, packetTablePos, SEEK_SET);
numBytes = fread(theReadBuffer, 1, kMaxBERSize, inputFile);
theInputPacketBytes = ReadBERInteger(theReadBuffer, &numBytes);
#if VERBOSE
printf ("theInputPacketBytes == %i bytes\n", theInputPacketBytes);
#endif
packetTablePos += numBytes;
fseek(inputFile, inputDataPos, SEEK_SET);
inputDataPos += theInputPacketBytes;
BitBufferReset(&theInputBuffer);
}
if (outputFileType != 'WAVE')
{
// cleanup -- write out the data size
fseek(outputFile, outputDataSizePos, SEEK_SET);
numDataBytes += kCAFFdataChunkEditsSize; // add in the edit bytes
#if VERBOSE
printf ("numDataBytes == %i bytes\n", numDataBytes);
#endif
WriteCAFFChunkSize(outputFile, numDataBytes);
}
else
{
// cleanup -- write out the data size
fseek(outputFile, outputDataSizePos, SEEK_SET);
WriteWAVEChunkSize(outputFile, (uint32_t)numDataBytes);
// write out the file size
fseek(outputFile, 4, SEEK_SET);
WriteWAVEChunkSize(outputFile, numDataBytes + sizeof(outputFileType) + kWAVEdataChunkHeaderSize + kWAVEfmtChunkSize); // add in the size for 'WAVE', size of the data' chunk header and the 'fmt ' chunk
}
delete theDecoder;
free(theReadBuffer);
free(theWriteBuffer);
return 0;
}
void GetOutputFileType(char * outputFileName, uint32_t * outputFileType)
{
char * typeStr = strrchr(outputFileName, '.');
*outputFileType = 'caff';
if (typeStr != NULL)
{
if (strlen(typeStr) == 4)
{
if (strcmp(typeStr, ".wav") == 0)
{
*outputFileType = 'WAVE';
}
}
}
}
ALACChannelLayoutTag GetALACChannelLayoutTag(uint32_t inChannelsPerFrame)
{
return ALACChannelLayoutTags[inChannelsPerFrame - 1];
}
void WriteWAVERIFFChunk(FILE * outputFile)
{
uint8_t theReadBuffer[kWAVERIFFChunkSize] = {'R', 'I', 'F', 'F', 0, 0, 0, 0, 'W', 'A', 'V', 'E'};
fwrite(theReadBuffer, 1, kWAVERIFFChunkSize, outputFile);
}
void WriteWAVEfmtChunk(FILE * outputFile, AudioFormatDescription theOutputFormat)
{
// we use a standard 'fmt ' chunk for our pcm data where 16 is the chunk size and 1 is the compression code
uint8_t theBuffer[kWAVEfmtChunkSize] = {'f', 'm', 't', ' ', 16, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32_t theSampleRate = theOutputFormat.mSampleRate;
uint32_t theAverageBytesPerSecond = theSampleRate * theOutputFormat.mBytesPerFrame;
theBuffer[10] = theOutputFormat.mChannelsPerFrame;
theBuffer[12] = theSampleRate & 0xff;
theBuffer[13] = (theSampleRate >> 8) & 0xff;
theBuffer[14] = (theSampleRate >> 16) & 0xff;
theBuffer[15] = theSampleRate >> 24;
theBuffer[16] = theAverageBytesPerSecond & 0xff;
theBuffer[17] = (theAverageBytesPerSecond >> 8) & 0xff;
theBuffer[18] = (theAverageBytesPerSecond >> 16) & 0xff;
theBuffer[19] = theAverageBytesPerSecond >> 24;
theBuffer[20] = theOutputFormat.mBytesPerFrame;
theBuffer[22] = theOutputFormat.mBitsPerChannel;
fwrite(theBuffer, 1, kWAVEfmtChunkSize, outputFile);
}
void WriteWAVEdataChunk(FILE * outputFile)
{
uint8_t theBuffer[kWAVEdataChunkHeaderSize] = {'d', 'a', 't', 'a', 0, 0, 0, 0};
fwrite(theBuffer, 1, kWAVEdataChunkHeaderSize, outputFile);
}
void WriteWAVEChunkSize(FILE * outputFile, uint32_t numDataBytes)
{
uint8_t theBuffer[4];
theBuffer[0] = numDataBytes & 0xff;
theBuffer[1] = (numDataBytes >> 8) & 0xff;
theBuffer[2] = (numDataBytes >> 16) & 0xff;
theBuffer[3] = (numDataBytes >> 24) & 0xff;
fwrite(theBuffer, 1, 4, outputFile);
}

View File

@@ -0,0 +1,202 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: ALACAudioTypes.h
*/
#ifndef ALACAUDIOTYPES_H
#define ALACAUDIOTYPES_H
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if PRAGMA_STRUCT_ALIGN
#pragma options align=mac68k
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(push, 2)
#elif PRAGMA_STRUCT_PACK
#pragma pack(2)
#endif
#include <stdint.h>
#if defined(__ppc__)
#define TARGET_RT_BIG_ENDIAN 1
#elif defined(__ppc64__)
#define TARGET_RT_BIG_ENDIAN 1
#endif
#define kChannelAtomSize 12
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmultichar"
enum
{
kALAC_UnimplementedError = -4,
kALAC_FileNotFoundError = -43,
kALAC_ParamError = -50,
kALAC_MemFullError = -108
};
enum
{
kALACFormatAppleLossless = 'alac',
kALACFormatLinearPCM = 'lpcm'
};
enum
{
kALACMaxChannels = 8,
kALACMaxEscapeHeaderBytes = 8,
kALACMaxSearches = 16,
kALACMaxCoefs = 16,
kALACDefaultFramesPerPacket = 4096
};
typedef uint32_t ALACChannelLayoutTag;
enum
{
kALACFormatFlagIsFloat = (1 << 0), // 0x1
kALACFormatFlagIsBigEndian = (1 << 1), // 0x2
kALACFormatFlagIsSignedInteger = (1 << 2), // 0x4
kALACFormatFlagIsPacked = (1 << 3), // 0x8
kALACFormatFlagIsAlignedHigh = (1 << 4), // 0x10
};
enum
{
#if TARGET_RT_BIG_ENDIAN
kALACFormatFlagsNativeEndian = kALACFormatFlagIsBigEndian
#else
kALACFormatFlagsNativeEndian = 0
#endif
};
// this is required to be an IEEE 64bit float
typedef double alac_float64_t;
// These are the Channel Layout Tags used in the Channel Layout Info portion of the ALAC magic cookie
enum
{
kALACChannelLayoutTag_Mono = (100<<16) | 1, // C
kALACChannelLayoutTag_Stereo = (101<<16) | 2, // L R
kALACChannelLayoutTag_MPEG_3_0_B = (113<<16) | 3, // C L R
kALACChannelLayoutTag_MPEG_4_0_B = (116<<16) | 4, // C L R Cs
kALACChannelLayoutTag_MPEG_5_0_D = (120<<16) | 5, // C L R Ls Rs
kALACChannelLayoutTag_MPEG_5_1_D = (124<<16) | 6, // C L R Ls Rs LFE
kALACChannelLayoutTag_AAC_6_1 = (142<<16) | 7, // C L R Ls Rs Cs LFE
kALACChannelLayoutTag_MPEG_7_1_B = (127<<16) | 8 // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
};
// ALAC currently only utilizes these channels layouts. There is a one for one correspondance between a
// given number of channels and one of these layout tags
static const ALACChannelLayoutTag ALACChannelLayoutTags[kALACMaxChannels] =
{
kALACChannelLayoutTag_Mono, // C
kALACChannelLayoutTag_Stereo, // L R
kALACChannelLayoutTag_MPEG_3_0_B, // C L R
kALACChannelLayoutTag_MPEG_4_0_B, // C L R Cs
kALACChannelLayoutTag_MPEG_5_0_D, // C L R Ls Rs
kALACChannelLayoutTag_MPEG_5_1_D, // C L R Ls Rs LFE
kALACChannelLayoutTag_AAC_6_1, // C L R Ls Rs Cs LFE
kALACChannelLayoutTag_MPEG_7_1_B // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
};
// AudioChannelLayout from CoreAudioTypes.h. We never need the AudioChannelDescription so we remove it
struct ALACAudioChannelLayout
{
ALACChannelLayoutTag mChannelLayoutTag;
uint32_t mChannelBitmap;
uint32_t mNumberChannelDescriptions;
};
typedef struct ALACAudioChannelLayout ALACAudioChannelLayout;
struct AudioFormatDescription
{
alac_float64_t mSampleRate;
uint32_t mFormatID;
uint32_t mFormatFlags;
uint32_t mBytesPerPacket;
uint32_t mFramesPerPacket;
uint32_t mBytesPerFrame;
uint32_t mChannelsPerFrame;
uint32_t mBitsPerChannel;
uint32_t mReserved;
};
typedef struct AudioFormatDescription AudioFormatDescription;
/* Lossless Definitions */
enum
{
kALACCodecFormat = 'alac',
kALACVersion = 0,
kALACCompatibleVersion = kALACVersion,
kALACDefaultFrameSize = 4096
};
// note: this struct is wrapped in an 'alac' atom in the sample description extension area
// note: in QT movies, it will be further wrapped in a 'wave' atom surrounded by 'frma' and 'term' atoms
typedef struct ALACSpecificConfig
{
uint32_t frameLength;
uint8_t compatibleVersion;
uint8_t bitDepth; // max 32
uint8_t pb; // 0 <= pb <= 255
uint8_t mb;
uint8_t kb;
uint8_t numChannels;
uint16_t maxRun;
uint32_t maxFrameBytes;
uint32_t avgBitRate;
uint32_t sampleRate;
} ALACSpecificConfig;
// The AudioChannelLayout atom type is not exposed yet so define it here
enum
{
AudioChannelLayoutAID = 'chan'
};
#pragma GCC diagnostic pop
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef __cplusplus
}
#endif
#endif /* ALACAUDIOTYPES_H */

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: ALACDecoder.h
*/
#ifndef _ALACDECODER_H
#define _ALACDECODER_H
#if PRAGMA_ONCE
#pragma once
#endif
#include <stdint.h>
#include "ALACAudioTypes.h"
struct BitBuffer;
class ALACDecoder
{
public:
ALACDecoder();
~ALACDecoder();
int32_t Init( void * inMagicCookie, uint32_t inMagicCookieSize );
int32_t Decode( struct BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples );
public:
// decoding parameters (public for use in the analyzer)
ALACSpecificConfig mConfig;
protected:
int32_t FillElement( struct BitBuffer * bits );
int32_t DataStreamElement( struct BitBuffer * bits );
uint16_t mActiveElements;
// decoding buffers
int32_t * mMixBufferU;
int32_t * mMixBufferV;
int32_t * mPredictor;
uint16_t * mShiftBuffer; // note: this points to mPredictor's memory but different
// variable for clarity and type difference
};
#endif /* _ALACDECODER_H */

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2011 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
/*
File: ALACEncoder.h
*/
#pragma once
#include <stdint.h>
#include "ALACAudioTypes.h"
struct BitBuffer;
class ALACEncoder
{
public:
ALACEncoder();
virtual ~ALACEncoder();
virtual int32_t Encode(AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat,
unsigned char * theReadBuffer, unsigned char * theWriteBuffer, int32_t * ioNumBytes);
virtual int32_t Finish( );
void SetFastMode( bool fast ) { mFastMode = fast; };
// this must be called *before* InitializeEncoder()
void SetFrameSize( uint32_t frameSize ) { mFrameSize = frameSize; };
void GetConfig( ALACSpecificConfig & config );
uint32_t GetMagicCookieSize(uint32_t inNumChannels);
void GetMagicCookie( void * config, uint32_t * ioSize );
virtual int32_t InitializeEncoder(AudioFormatDescription theOutputFormat);
protected:
virtual void GetSourceFormat( const AudioFormatDescription * source, AudioFormatDescription * output );
int32_t EncodeStereo( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
int32_t EncodeStereoFast( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
int32_t EncodeStereoEscape( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t numSamples );
int32_t EncodeMono( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
// ALAC encoder parameters
int16_t mBitDepth;
bool mFastMode;
// encoding state
int16_t mLastMixRes[kALACMaxChannels];
// encoding buffers
int32_t * mMixBufferU;
int32_t * mMixBufferV;
int32_t * mPredictorU;
int32_t * mPredictorV;
uint16_t * mShiftBufferUV;
uint8_t * mWorkBuffer;
// per-channel coefficients buffers
int16_t mCoefsU[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
int16_t mCoefsV[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
// encoding statistics
uint32_t mTotalBytesGenerated;
uint32_t mAvgBitRate;
uint32_t mMaxFrameBytes;
uint32_t mFrameSize;
uint32_t mMaxOutputBytes;
uint32_t mNumChannels;
uint32_t mOutputSampleRate;
};

View File

@@ -0,0 +1,23 @@
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[Makefile]
indent_style = tab
indent_size = unset
# ignore external repositories and test inputs
[tests/{unity,json-patch-tests,inputs}/*]
indent_style = unset
indent_size = unset
end_of_line = unset
charset = unset
trim_trailing_whitespace = unset
insert_final_newline = unset

View File

@@ -0,0 +1,11 @@
* text=auto
/tests/inputs/* text eol=lf
.gitattributes export-ignore
.gitignore export-ignore
.github export-ignore
.editorconfig export-ignore
.travis.yml export-ignore
# Linguist incorrectly identified the headers as C++, manually override this.
*.h linguist-language=C

View File

@@ -0,0 +1,54 @@
Contribution Guidelines
=======================
Contributions to cJSON are welcome. If you find a bug or want to improve cJSON in another way, pull requests are appreciated.
For bigger changes, in order to avoid wasted effort, please open an issue to discuss the technical details before creating a pull request.
The further sections explain the process in more detail and provides some guidelines on how contributions should look like.
Branches
--------
There are two branches to be aware of, the `master` and the `develop` branch. The `master` branch is reserved for the latest release, so only make pull requests to the `master` branch for small bug- or security fixes (these are usually just a few lines). In all other cases, please make a pull request to the `develop` branch.
Coding Style
------------
The coding style has been discussed in [#24](https://github.com/DaveGamble/cJSON/issues/24). The basics are:
* Use 4 spaces for indentation
* No oneliners (conditions, loops, variable declarations ...)
* Always use parenthesis for control structures
* Don't implicitly rely on operator precedence, use round brackets in expressions. e.g. `(a > b) && (c < d)` instead of `a>b && c<d`
* opening curly braces start in the next line
* use spaces around operators
* lines should not have trailing whitespace
* use spaces between function parameters
* use pronouncable variable names, not just a combination of letters
Example:
```c
/* calculate the new length of the string in a printbuffer and update the offset */
static void update_offset(printbuffer * const buffer)
{
const unsigned char *buffer_pointer = NULL;
if ((buffer == NULL) || (buffer->buffer == NULL))
{
return;
}
buffer_pointer = buffer->buffer + buffer->offset;
buffer->offset += strlen((const char*)buffer_pointer);
}
```
Unit Tests
----------
cJSON uses the [Unity](https://github.com/ThrowTheSwitch/Unity) library for unit tests. The tests are located in the `tests` directory. In order to add a new test, either add it to one of the existing files (if it fits) or add a new C file for the test. That new file has to be added to the list of tests in `tests/CMakeLists.txt`.
All new features have to be covered by unit tests.
Other Notes
-----------
* Internal functions are to be declared static.
* Wrap the return type of external function in the `CJSON_PUBLIC` macro.

View File

@@ -0,0 +1,102 @@
name: CI
on:
push:
branches: [ master ]
paths-ignore:
- '**.md'
- 'LICENSE'
pull_request:
types: [opened, synchronize]
paths-ignore:
- '**.md'
- 'LICENSE'
jobs:
linux:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
mem_check:
- ENABLE_VALGRIND
- ENABLE_SANITIZERS
- NONE_MEM_CHECK
compiler:
- GCC
- CLANG
steps:
- uses: actions/checkout@v2
- name: install build dependencies
run: |
sudo apt-get update
sudo apt-get install clang-8 valgrind
- name: build and test
shell: bash
run: |
if [ "${{ matrix.mem_check }}" == "ENABLE_VALGRIND" ]; then
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=ON -DENABLE_SAFE_STACK=ON -DENABLE_SANITIZERS=OFF"
elif [ "${{ matrix.mem_check }}" == "ENABLE_SANITIZERS" ]; then
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=ON"
else
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=OFF"
fi
if [ "${{ matrix.compiler }}" == "GCC" ]; then
export CC=gcc
else
export CC=clang
fi
#run build and test
JOBS=20
export CTEST_PARALLEL_LEVEL=$JOBS
export CTEST_OUTPUT_ON_FAILURE=1
mkdir -p build
cd build
echo [cmake]: cmake .. $EVENT_CMAKE_OPTIONS
cmake .. $EVENT_CMAKE_OPTIONS || (rm -rf * && cmake .. $EVENT_CMAKE_OPTIONS)
cmake --build .
make
make test
macos:
runs-on: macos-latest
if: "!contains(github.event.head_commit.message, 'ci skip')"
strategy:
fail-fast: false
matrix:
mem_check:
- ENABLE_VALGRIND
- ENABLE_SANITIZERS
- NONE_MEM_CHECK
compiler:
- GCC
- CLANG
steps:
- uses: actions/checkout@v2
- name: build and test
shell: bash
run: |
if [ "${{ matrix.mem_check }}" == "ENABLE_VALGRIND" ]; then
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=ON -DENABLE_SAFE_STACK=ON -DENABLE_SANITIZERS=OFF"
elif [ "${{ matrix.mem_check }}" == "ENABLE_SANITIZERS" ]; then
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=ON"
else
EVENT_CMAKE_OPTIONS="-DENABLE_CJSON_UTILS=ON -DENABLE_VALGRIND=OFF -DENABLE_SAFE_STACK=OFF -DENABLE_SANITIZERS=OFF"
fi
if [ "${{ matrix.compiler }}" == "GCC" ]; then
export CC=gcc
else
export CC=clang
fi
#run build and test
JOBS=20
export CTEST_PARALLEL_LEVEL=$JOBS
export CTEST_OUTPUT_ON_FAILURE=1
mkdir -p build
cd build
echo [cmake]: cmake .. $EVENT_CMAKE_OPTIONS
cmake .. $EVENT_CMAKE_OPTIONS || (rm -rf * && cmake .. $EVENT_CMAKE_OPTIONS)
cmake --build .
make
make test

View File

@@ -0,0 +1,20 @@
.svn
test
*.o
*.a
*.so
*.swp
*.patch
tags
*.dylib
build/
cJSON_test
cJSON_test_utils
libcjson.so.*
libcjson_utils.so.*
*.orig
.vscode
.idea
cmake-build-debug
*.lst
*.lss

View File

@@ -0,0 +1,28 @@
dist: trusty
sudo: false
language: c
env:
matrix:
- VALGRIND=On SANITIZERS=Off
- VALGRIND=Off SANITIZERS=Off
- VALGRIND=Off SANITIZERS=On
compiler:
- gcc
- clang
addons:
apt:
packages:
- valgrind
- libasan0
- lib32asan0
# currently not supported on travis:
# - libasan1
# - libasan2
# - libubsan0
- llvm
script:
- mkdir build
- cd build
- cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_VALGRIND="${VALGRIND}" -DENABLE_SAFE_STACK="${VALGRIND}" -DENABLE_SANITIZERS="${SANITIZERS}"
- make
- make test CTEST_OUTPUT_ON_FAILURE=On

View File

@@ -0,0 +1,428 @@
1.7.15 (Aug 25, 2021)
======
Fixes:
------
* Fix potential core dumped for strrchr, see [#546](https://github.com/DaveGamble/cJSON/pull/546)
* Fix null pointer crash in cJSON_CreateXxArray, see [#538](https://github.com/DaveGamble/cJSON/pull/538)
* Fix several null pointer problems on allocation failure, see [#526](https://github.com/DaveGamble/cJSON/pull/526)
* Fix a possible dereference of null pointer, see [#519](https://github.com/DaveGamble/cJSON/pull/519)
* Fix windows build failure about defining nan, see [#518](https://github.com/DaveGamble/cJSON/pull/518)
1.7.14 (Sep 3, 2020)
======
Fixes:
------
* optimize the way to find tail node, see [#503](https://github.com/DaveGamble/cJSON/pull/503)
* Fix WError error on macosx because NAN is a float. Thanks @sappo, see [#484](https://github.com/DaveGamble/cJSON/pull/484)
* Fix some bugs in detach and replace. Thanks @miaoerduo, see [#456](https://github.com/DaveGamble/cJSON/pull/456)
1.7.13 (Apr 2, 2020)
======
Features:
---------
* add new API of cJSON_ParseWithLength without breaking changes. Thanks @caglarivriz, see [#358](https://github.com/DaveGamble/cJSON/pull/358)
* add new API of cJSON_GetNumberValue. Thanks @Intuition, see[#385](https://github.com/DaveGamble/cJSON/pull/385)
* add uninstall target function for CMake. See [#402](https://github.com/DaveGamble/cJSON/pull/402)
* Improve performance of adding item to array. Thanks @xiaomianhehe, see [#430](https://github.com/DaveGamble/cJSON/pull/430), [#448](https://github.com/DaveGamble/cJSON/pull/448)
* add new API of cJSON_SetValuestring, for changing the valuestring safely. See [#451](https://github.com/DaveGamble/cJSON/pull/451)
* add return value for cJSON_AddItemTo... and cJSON_ReplaceItem... (check if the operation successful). See [#453](https://github.com/DaveGamble/cJSON/pull/453)
Fixes:
------
* Fix clang -Wfloat-equal warning. Thanks @paulmalovanyi, see [#368](https://github.com/DaveGamble/cJSON/pull/368)
* Fix make failed in mac os. See [#405](https://github.com/DaveGamble/cJSON/pull/405)
* Fix memory leak in cJSONUtils_FindPointerFromObjectTo. Thanks @andywolk for reporting, see [#414](https://github.com/DaveGamble/cJSON/issues/414)
* Fix bug in encode_string_as_pointer. Thanks @AIChangJiang for reporting, see [#439](https://github.com/DaveGamble/cJSON/issues/439)
1.7.12 (May 17, 2019)
======
Fixes:
------
* Fix infinite loop in `cJSON_Minify` (potential Denial of Service). Thanks @Alanscut for reporting, see [#354](https://github.com/DaveGamble/cJSON/issues/354)
* Fix link error for Visual Studio. Thanks @tan-wei, see [#352](https://github.com/DaveGamble/cJSON/pull/352).
* Undefine `true` and `false` for `cJSON_Utils` before redefining them. Thanks @raiden00pl, see [#347](https://github.com/DaveGamble/cJSON/pull/347).
1.7.11 (Apr 15, 2019)
======
Fixes:
------
* Fix a bug where cJSON_Minify could overflow it's buffer, both reading and writing. This is a security issue, see [#338](https://github.com/DaveGamble/cJSON/issues/338). Big thanks @bigric3 for reporting.
* Unset `true` and `false` macros before setting them if they exist. See [#339](https://github.com/DaveGamble/cJSON/issues/339), thanks @raiden00pl for reporting
1.7.10 (Dec 21, 2018)
======
Fixes:
------
* Fix package config file for `libcjson`. Thanks @shiluotang for reporting [#321](https://github.com/DaveGamble/cJSON/issues/321)
* Correctly split lists in `cJSON_Utils`'s merge sort. Thanks @andysCaplin for the fix [#322](https://github.com/DaveGamble/cJSON/issues/322)
1.7.9 (Dec 16, 2018)
=====
Fixes:
------
* Fix a bug where `cJSON_GetObjectItemCaseSensitive` would pass a nullpointer to `strcmp` when called on an array, see [#315](https://github.com/DaveGamble/cJSON/issues/315). Thanks @yuweol for reporting.
* Fix error in `cJSON_Utils` where the case sensitivity was not respected, see [#317](https://github.com/DaveGamble/cJSON/pull/317). Thanks @yuta-oxo for fixing.
* Fix some warnings detected by the Visual Studio Static Analyzer, see [#307](https://github.com/DaveGamble/cJSON/pull/307). Thanks @bnason-nf
1.7.8 (Sep 22, 2018)
======
Fixes:
------
* cJSON now works with the `__stdcall` calling convention on Windows, see [#295](https://github.com/DaveGamble/cJSON/pull/295), thanks @zhindes for contributing
1.7.7 (May 22, 2018)
=====
Fixes:
------
* Fix a memory leak when realloc fails, see [#267](https://github.com/DaveGamble/cJSON/issues/267), thanks @AlfieDeng for reporting
* Fix a typo in the header file, see [#266](https://github.com/DaveGamble/cJSON/pull/266), thanks @zhaozhixu
1.7.6 (Apr 13, 2018)
=====
Fixes:
------
* Add `SONAME` to the ELF files built by the Makefile, see [#252](https://github.com/DaveGamble/cJSON/issues/252), thanks @YanhaoMo for reporting
* Add include guards and `extern "C"` to `cJSON_Utils.h`, see [#256](https://github.com/DaveGamble/cJSON/issues/256), thanks @daschfg for reporting
Other changes:
* Mark the Makefile as deprecated in the README.
1.7.5 (Mar 23, 2018)
=====
Fixes:
------
* Fix a bug in the JSON Patch implementation of `cJSON Utils`, see [#251](https://github.com/DaveGamble/cJSON/pull/251), thanks @bobkocisko.
1.7.4 (Mar 3, 2018)
=====
Fixes:
------
* Fix potential use after free if the `string` parameter to `cJSON_AddItemToObject` is an alias of the `string` property of the object that is added,see [#248](https://github.com/DaveGamble/cJSON/issues/248). Thanks @hhallen for reporting.
1.7.3 (Feb 8, 2018)
=====
Fixes:
------
* Fix potential double free, thanks @projectgus for reporting [#241](https://github.com/DaveGamble/cJSON/issues/241)
1.7.2 (Feb 6, 2018)
=====
Fixes:
------
* Fix the use of GNUInstallDirs variables and the pkgconfig file. Thanks @zeerd for reporting [#240](https://github.com/DaveGamble/cJSON/pull/240)
1.7.1 (Jan 10, 2018)
=====
Fixes:
------
* Fixed an Off-By-One error that could lead to an out of bounds write. Thanks @liuyunbin for reporting [#230](https://github.com/DaveGamble/cJSON/issues/230)
* Fixed two errors with buffered printing. Thanks @liuyunbin for reporting [#230](https://github.com/DaveGamble/cJSON/issues/230)
1.7.0 (Dec 31, 2017)
=====
Features:
---------
* Large rewrite of the documentation, see [#215](https://github.com/DaveGamble/cJSON/pull/215)
* Added the `cJSON_GetStringValue` function
* Added the `cJSON_CreateStringReference` function
* Added the `cJSON_CreateArrayReference` function
* Added the `cJSON_CreateObjectReference` function
* The `cJSON_Add...ToObject` macros are now functions that return a pointer to the added item, see [#226](https://github.com/DaveGamble/cJSON/pull/226)
Fixes:
------
* Fix a problem with `GNUInstallDirs` in the CMakeLists.txt, thanks @yangfl, see [#210](https://github.com/DaveGamble/cJSON/pull/210)
* Fix linking the tests when building as static library, see [#213](https://github.com/DaveGamble/cJSON/issues/213)
* New overrides for the CMake option `BUILD_SHARED_LIBS`, see [#207](https://github.com/DaveGamble/cJSON/issues/207)
Other Changes:
--------------
* Readme: Explain how to include cJSON, see [#211](https://github.com/DaveGamble/cJSON/pull/211)
* Removed some trailing spaces in the code, thanks @yangfl, see [#212](https://github.com/DaveGamble/cJSON/pull/212)
* Updated [Unity](https://github.com/ThrowTheSwitch/Unity) and [json-patch-tests](https://github.com/json-patch/json-patch-tests)
1.6.0 (Oct 9, 2017)
=====
Features:
---------
* You can now build cJSON as both shared and static library at once with CMake using `-DBUILD_SHARED_AND_STATIC_LIBS=On`, see [#178](https://github.com/DaveGamble/cJSON/issues/178)
* UTF-8 byte order marks are now ignored, see [#184](https://github.com/DaveGamble/cJSON/issues/184)
* Locales can now be disabled with the option `-DENABLE_LOCALES=Off`, see [#202](https://github.com/DaveGamble/cJSON/issues/202), thanks @Casperinous
* Better support for MSVC and Visual Studio
Other Changes:
--------------
* Add the new warnings `-Wswitch-enum`, `-Wused-but-makred-unused`, `-Wmissing-variable-declarations`, `-Wunused-macro`
* More number printing tests.
* Continuous integration testing with AppVeyor (semi automatic at this point), thanks @simon-p-r
1.5.9 (Sep 8, 2017)
=====
Fixes:
------
* Set the global error pointer even if `return_parse_end` is passed to `cJSON_ParseWithOpts`, see [#200](https://github.com/DaveGamble/cJSON/pull/200), thanks @rmallins
1.5.8 (Aug 21, 2017)
=====
Fixes:
------
* Fix `make test` in the Makefile, thanks @YanhaoMo for reporting this [#195](https://github.com/DaveGamble/cJSON/issues/195)
1.5.7 (Jul 13, 2017)
=====
Fixes:
------
* Fix a bug where realloc failing would return a pointer to an invalid memory address. This is a security issue as it could potentially be used by an attacker to write to arbitrary memory addresses, see [#189](https://github.com/DaveGamble/cJSON/issues/189), fixed in [954d61e](https://github.com/DaveGamble/cJSON/commit/954d61e5e7cb9dc6c480fc28ac1cdceca07dd5bd), big thanks @timothyjohncarney for reporting this issue
* Fix a spelling mistake in the AFL fuzzer dictionary, see [#185](https://github.com/DaveGamble/cJSON/pull/185), thanks @jwilk
1.5.6 (Jun 28, 2017)
=====
Fixes:
------
* Make cJSON a lot more tolerant about passing NULL pointers to its functions, it should now fail safely instead of dereferencing the pointer, see [#183](https://github.com/DaveGamble/cJSON/pull/183). Thanks @msichal for reporting [#182](https://github.com/DaveGamble/cJSON/issues/182)
1.5.5 (Jun 15, 2017)
=====
Fixes:
------
* Fix pointers to nested arrays in cJSON_Utils, see [9abe](https://github.com/DaveGamble/cJSON/commit/9abe75e072050f34732a7169740989a082b65134)
* Fix an error with case sensitivity handling in cJSON_Utils, see [b9cc911](https://github.com/DaveGamble/cJSON/commit/b9cc911831b0b3e1bb72f142389428e59f882b38)
* Fix cJSON_Compare for arrays that are prefixes of the other and objects that are a subset of the other, see [03ba72f](https://github.com/DaveGamble/cJSON/commit/03ba72faec115160d1f3aea5582d9b6af5d3e473) and [#180](https://github.com/DaveGamble/cJSON/issues/180), thanks @zhengqb for reporting
1.5.4 (Jun 5, 2017)
======
Fixes:
------
* Fix build with GCC 7.1.1 and optimization level `-O2`, see [bfbd8fe](https://github.com/DaveGamble/cJSON/commit/bfbd8fe0d85f1dd21e508748fc10fc4c27cc51be)
Other Changes:
--------------
* Update [Unity](https://github.com/ThrowTheSwitch/Unity) to 3b69beaa58efc41bbbef70a32a46893cae02719d
1.5.3 (May 23, 2017)
=====
Fixes:
------
* Fix `cJSON_ReplaceItemInObject` not keeping the name of an item, see [#174](https://github.com/DaveGamble/cJSON/issues/174)
1.5.2 (May 10, 2017)
=====
Fixes:
------
* Fix a reading buffer overflow in `parse_string`, see [a167d9e](https://github.com/DaveGamble/cJSON/commit/a167d9e381e5c84bc03de4e261757b031c0c690d)
* Fix compiling with -Wcomma, see [186cce3](https://github.com/DaveGamble/cJSON/commit/186cce3ece6ce6dfcb58ac8b2a63f7846c3493ad)
* Remove leftover attribute from tests, see [b537ca7](https://github.com/DaveGamble/cJSON/commit/b537ca70a35680db66f1f5b8b437f7114daa699a)
1.5.1 (May 6, 2017)
=====
Fixes:
------
* Add gcc version guard to the Makefile, see [#164](https://github.com/DaveGamble/cJSON/pull/164), thanks @juvasquezg
* Fix incorrect free in `cJSON_Utils` if custom memory allocator is used, see [#166](https://github.com/DaveGamble/cJSON/pull/166), thanks @prefetchnta
1.5.0 (May 2, 2017)
=====
Features:
* cJSON finally prints numbers without losing precision, see [#153](https://github.com/DaveGamble/cJSON/pull/153), thanks @DeboraG
* `cJSON_Compare` recursively checks if two cJSON items contain the same values, see [#148](https://github.com/DaveGamble/cJSON/pull/148)
* Provide case sensitive versions of every function where it matters, see [#158](https://github.com/DaveGamble/cJSON/pull/158) and [#159](https://github.com/DaveGamble/cJSON/pull/159)
* Added `cJSON_ReplaceItemViaPointer` and `cJSON_DetachItemViaPointer`
* Added `cJSON_free` and `cJSON_malloc` that expose the internal configured memory allocators. see [02a05ee](https://github.com/DaveGamble/cJSON/commit/02a05eea4e6ba41811f130b322660bea8918e1a0)
Enhancements:
-------------
* Parse into a buffer, this will allow parsing `\u0000` in the future (not quite yet though)
* General simplifications and readability improvements
* More unit tests
* Update [unity](https://github.com/ThrowTheSwitch/Unity) testing library to 2.4.1
* Add the [json-patch-tests](https://github.com/json-patch/json-patch-tests) test suite to test cJSON_Utils.
* Move all tests from `test_utils.c` to unit tests with unity.
Fixes:
------
* Fix some warnings with the Microsoft compiler, see [#139](https://github.com/DaveGamble/cJSON/pull/139), thanks @PawelWMS
* Fix several bugs in cJSON_Utils, mostly found with [json-patch-tests](https://github.com/json-patch/json-patch-tests)
* Prevent a stack overflow by specifying a maximum nesting depth `CJSON_NESTING_LIMIT`
Other Changes:
--------------
* Move generated files in the `library_config` subdirectory.
1.4.7 (Apr 19, 2017)
=====
Fixes:
------
* Fix `cJSONUtils_ApplyPatches`, it was completely broken and apparently nobody noticed (or at least reported it), see [075a06f](https://github.com/DaveGamble/cJSON/commit/075a06f40bdc4f836c7dd7cad690d253a57cfc50)
* Fix inconsistent prototype for `cJSON_GetObjectItemCaseSensitive`, see [51d3df6](https://github.com/DaveGamble/cJSON/commit/51d3df6c9f7b56b860c8fb24abe7bab255cd4fa9), thanks @PawelWMS
1.4.6 (Apr 9, 2017)
=====
Fixes:
------
* Several corrections in the README
* Making clear that `valueint` should not be written to
* Fix overflow detection in `ensure`, see [2683d4d](https://github.com/DaveGamble/cJSON/commit/2683d4d9873df87c4bdccc523903ddd78d1ad250)
* Fix a potential null pointer dereference in cJSON_Utils, see [795c3ac](https://github.com/DaveGamble/cJSON/commit/795c3acabed25c9672006b2c0f40be8845064827)
* Replace incorrect `sizeof('\0')` with `sizeof("")`, see [84237ff](https://github.com/DaveGamble/cJSON/commit/84237ff48e69825c94261c624eb0376d0c328139)
* Add caveats section to the README, see [50b3c30](https://github.com/DaveGamble/cJSON/commit/50b3c30dfa89830f8f477ce33713500740ac3b79)
* Make cJSON locale independent, see [#146](https://github.com/DaveGamble/cJSON/pull/146), Thanks @peterh for reporting
* Fix compiling without CMake with MSVC, see [#147](https://github.com/DaveGamble/cJSON/pull/147), Thanks @dertuxmalwieder for reporting
1.4.5 (Mar 28, 2017)
=====
Fixes:
------
* Fix bug in `cJSON_SetNumberHelper`, thanks @mmkeeper, see [#138](https://github.com/DaveGamble/cJSON/issues/138) and [ef34500](https://github.com/DaveGamble/cJSON/commit/ef34500693e8c4a2849d41a4bd66fd19c9ec46c2)
* Workaround for internal compiler error in GCC 5.4.0 and 6.3.1 on x86 (2f65e80a3471d053fdc3f8aed23d01dd1782a5cb [GCC bugreport](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80097))
1.4.4 (Mar 24, 2017)
=====
Fixes:
------
* Fix a theoretical integer overflow, (not sure if it is possible on actual hardware), see [e58f7ec](https://github.com/DaveGamble/cJSON/commit/e58f7ec027d00b7cdcbf63e518c1b5268b29b3da)
* Fix an off by one error, see [cc84a44](https://github.com/DaveGamble/cJSON/commit/cc84a446be20cc283bafdc4d94c050ba1111ac02), thanks @gatzka
* Double check the offset of the print buffer in `ensure`, see [1934059](https://github.com/DaveGamble/cJSON/commit/1934059554b9a0971e00f79e96900f422cfdd114)
Improvements:
* Add a note in the header about required buffer size when using `cJSON_PrintPreallocated`, see [4bfb8800](https://github.com/DaveGamble/cJSON/commit/4bfb88009342fb568295a7f6dc4b7fee74fbf022)
1.4.3 (Mar 19, 2017)
=====
Fixes:
------
* Fix compilation of the tests on 32 bit PowerPC and potentially other systems, see [4ec6e76](https://github.com/DaveGamble/cJSON/commit/4ec6e76ea2eec16f54b58e8c95b4c734e59481e4)
* Fix compilation with old GCC compilers (4.3+ were tested), see [227d33](https://github.com/DaveGamble/cJSON/commit/227d3398d6b967879761ebe02c1b63dbd6ea6e0d), [466eb8e](https://github.com/DaveGamble/cJSON/commit/466eb8e3f8a65080f2b3ca4a79ab7b72bd539dba), see also [#126](https://github.com/DaveGamble/cJSON/issues/126)
1.4.2 (Mar 16, 2017)
=====
Fixes:
------
* Fix minimum required cmake version, see [30e1e7a](https://github.com/DaveGamble/cJSON/commit/30e1e7af7c63db9b55f5a3cda977a6c032f0b132)
* Fix detection of supported compiler flags, see [76e5296](https://github.com/DaveGamble/cJSON/commit/76e5296d0d05ceb3018a9901639e0e171b44a557)
* Run `cJSON_test` and `cJSON_test_utils` along with unity tests, see [c597601](https://github.com/DaveGamble/cJSON/commit/c597601cf151a757dcf800548f18034d4ddfe2cb)
1.4.1 (Mar 16, 2017)
=====
Fixes:
------
* Make `print_number` abort with a failure in out of memory situations, see [cf1842](https://github.com/DaveGamble/cJSON/commit/cf1842dc6f64c49451a022308b4415e4d468be0a)
1.4.0 (Mar 4, 2017)
=====
Features
--------
* Functions to check the type of an item, see [#120](https://github.com/DaveGamble/cJSON/pull/120)
* Use dllexport on windows and fvisibility on Unix systems for public functions, see [#116](https://github.com/DaveGamble/cJSON/pull/116), thanks @mjerris
* Remove trailing zeroes from printed numbers, see [#123](https://github.com/DaveGamble/cJSON/pull/123)
* Expose the internal boolean type `cJSON_bool` in the header, see [2d3520e](https://github.com/DaveGamble/cJSON/commit/2d3520e0b9d0eb870e8886e8a21c571eeddbb310)
Fixes
* Fix handling of NULL pointers in `cJSON_ArrayForEach`, see [b47d0e3](https://github.com/DaveGamble/cJSON/commit/b47d0e34caaef298edfb7bd09a72cfff21d231ff)
* Make it compile with GCC 7 (fix -Wimplicit-fallthrough warning), see [9d07917](https://github.com/DaveGamble/cJSON/commit/9d07917feb1b613544a7513d19233d4c851ad7ad)
Other Improvements
* internally use realloc if available ([#110](https://github.com/DaveGamble/cJSON/pull/110))
* builtin support for fuzzing with [afl](http://lcamtuf.coredump.cx/afl/) ([#111](https://github.com/DaveGamble/cJSON/pull/111))
* unit tests for the print functions ([#112](https://github.com/DaveGamble/cJSON/pull/112))
* Always use buffered printing ([#113](https://github.com/DaveGamble/cJSON/pull/113))
* simplify the print functions ([#114](https://github.com/DaveGamble/cJSON/pull/114))
* Add the compiler flags `-Wdouble-conversion`, `-Wparentheses` and `-Wcomma` ([#122](https://github.com/DaveGamble/cJSON/pull/122))
1.3.2 (Mar 1, 2017)
=====
Fixes:
------
* Don't build the unity library if testing is disabled, see [#121](https://github.com/DaveGamble/cJSON/pull/121). Thanks @ffontaine
1.3.1 (Feb 27, 2017)
=====
Fixes:
------
* Bugfix release that fixes an out of bounds read, see [#118](https://github.com/DaveGamble/cJSON/pull/118). This shouldn't have any security implications.
1.3.0 (Feb 17, 2017)
=====
This release includes a lot of rework in the parser and includes the Cunity unit testing framework, as well as some fixes. I increased the minor version number because there were quite a lot of internal changes.
Features:
* New type for cJSON structs: `cJSON_Invalid`, see [#108](https://github.com/DaveGamble/cJSON/pull/108)
Fixes:
------
* runtime checks for a lot of potential integer overflows
* fix incorrect return in cJSON_PrintBuffered [cf9d57d](https://github.com/DaveGamble/cJSON/commit/cf9d57d56cac21fc59465b8d26cf29bf6d2a87b3)
* fix several potential issues found by [Coverity](https://scan.coverity.com/projects/cjson)
* fix potentially undefined behavior when assigning big numbers to `valueint` ([41e2837](https://github.com/DaveGamble/cJSON/commit/41e2837df1b1091643aff073f2313f6ff3cc10f4))
* Numbers exceeding `INT_MAX` or lower than `INT_MIN` will be explicitly assigned to `valueint` as `INT_MAX` and `INT_MIN` respectively (saturation on overflow).
* fix the `cJSON_SetNumberValue` macro ([87f7727](https://github.com/DaveGamble/cJSON/commit/87f77274de6b3af00fb9b9a7f3b900ef382296c2)), this slightly changes the behavior, see commit message
Introduce unit tests
--------------------
* Started writing unit tests with the [Cunity](https://github.com/ThrowTheSwitch/Unity) testing framework. Currently this covers the parser functions.
Also:
* Support for running the tests with [Valgrind](http://valgrind.org)
* Support for compiling the tests with [AddressSanitizer](https://github.com/google/sanitizers) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
* `travis.yml` file for running unit tests on travis. (not enabled for the repository yet though [#102](https://github.com/DaveGamble/cJSON/issues/102)
Simplifications
---------------
After having unit tests for the parser function in place, I started refactoring the parser functions (as well as others) and making them easier to read and maintain.
* Use `strtod` from the standard library for parsing numbers ([0747669](https://github.com/DaveGamble/cJSON/commit/074766997246481dfc72bfa78f07898a2716473f))
* Use goto-fail in several parser functions ([#100](https://github.com/DaveGamble/cJSON/pull/100))
* Rewrite/restructure all of the parsing functions to be easier to understand and have less code paths doing the same as another. ([#109](https://github.com/DaveGamble/cJSON/pull/109))
* Simplify the buffer allocation strategy to always doubling the needed amount ([9f6fa94](https://github.com/DaveGamble/cJSON/commit/9f6fa94c91a87b71e4c6868dbf2ce431a48517b0))
* Combined `cJSON_AddItemToObject` and `cJSON_AddItemToObjectCS` to one function ([cf862d](https://github.com/DaveGamble/cJSON/commit/cf862d0fed7f9407e4b046d78d3d8050d2080d12))
Other changes
-------------
* Prevent the usage of incompatible C and header versions via preprocessor directive ([123bb1](https://github.com/DaveGamble/cJSON/commit/123bb1af7bfae41d805337fef4b41045ef6c7d25))
* Let CMake automatically detect compiler flags
* Add new compiler flags (`-Wundef`, `-Wswitch-default`, `-Wconversion`, `-fstack-protector-strong`) ([#98](https://github.com/DaveGamble/cJSON/pull/98))
* Change internal sizes from `int` to `size_t` ([ecd5678](https://github.com/DaveGamble/cJSON/commit/ecd5678527a6bc422da694e5be9e9979878fe6a0))
* Change internal strings from `char*` to `unsigned char*` ([28b9ba4](https://github.com/DaveGamble/cJSON/commit/28b9ba4334e0f7309e867e874a31f395c0ac2474))
* Add `const` in more places
1.2.1 (Jan 31, 2017)
=====
Fixes:
------
* Fixes a potential null pointer dereference in cJSON_Utils, discovered using clang's static analyzer by @bnason-nf, see [#96](https://github.com/DaveGamble/cJSON/issues/96)
1.2.0 (Jan 9, 2017)
=====
Features:
---------
* Add a new type of cJSON item for raw JSON and support printing it. Thanks @loigu, see [#65](https://github.com/DaveGamble/cJSON/pull/65), [#90](https://github.com/DaveGamble/cJSON/pull/90)
Fixes:
------
* Compiler warning if const is casted away, Thanks @gatzka, see [#83](https://github.com/DaveGamble/cJSON/pull/83)
* Fix compile error with strict-overflow on PowerPC, see [#85](https://github.com/DaveGamble/cJSON/issues/85)
* Fix typo in the README, thanks @MicroJoe, see [#88](https://github.com/DaveGamble/cJSON/pull/88)
* Add compile flag for compatibility with C++ compilers
1.1.0 (Dec 6, 2016)
=====
* Add a function `cJSON_PrintPreallocated` to print to a preallocated buffer, thanks @ChisholmKyle, see [#72](https://github.com/DaveGamble/cJSON/pull/72)
* More compiler warnings when using Clang or GCC, thanks @gatzka, see [#75](https://github.com/DaveGamble/cJSON/pull/75), [#78](https://github.com/DaveGamble/cJSON/pull/78)
* fixed a memory leak in `cJSON_Duplicate`, thanks @alperakcan, see [#81](https://github.com/DaveGamble/cJSON/pull/81)
* fix the `ENABLE_CUSTOM_COMPILER_FLAGS` cmake option
1.0.2 (Nov 25, 2016)
=====
* Rename internal boolean type, see [#71](https://github.com/DaveGamble/cJSON/issues/71).
1.0.1 (Nov 20, 2016)
=====
Small bugfix release.
* Fixes a bug with the use of the cJSON structs type in cJSON_Utils, see [d47339e](https://github.com/DaveGamble/cJSON/commit/d47339e2740360e6e0994527d5e4752007480f3a)
* improve code readability
* initialize all variables
1.0.0 (Nov 17, 2016)
=====
This is the first official versioned release of cJSON. It provides an API version for the shared library and improved Makefile and CMake build files.

View File

@@ -0,0 +1,270 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
cmake_minimum_required(VERSION 3.0)
project(cJSON
VERSION 1.7.15
LANGUAGES C)
cmake_policy(SET CMP0054 NEW) # set CMP0054 policy
include(GNUInstallDirs)
set(CJSON_VERSION_SO 1)
set(CJSON_UTILS_VERSION_SO 1)
set(custom_compiler_flags)
include(CheckCCompilerFlag)
option(ENABLE_CUSTOM_COMPILER_FLAGS "Enables custom compiler flags" ON)
if (ENABLE_CUSTOM_COMPILER_FLAGS)
if (("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU"))
list(APPEND custom_compiler_flags
-std=c89
-pedantic
-Wall
-Wextra
-Werror
-Wstrict-prototypes
-Wwrite-strings
-Wshadow
-Winit-self
-Wcast-align
-Wformat=2
-Wmissing-prototypes
-Wstrict-overflow=2
-Wcast-qual
-Wundef
-Wswitch-default
-Wconversion
-Wc++-compat
-fstack-protector-strong
-Wcomma
-Wdouble-promotion
-Wparentheses
-Wformat-overflow
-Wunused-macros
-Wmissing-variable-declarations
-Wused-but-marked-unused
-Wswitch-enum
)
elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
# Disable warning c4001 - nonstandard extension 'single line comment' was used
# Define _CRT_SECURE_NO_WARNINGS to disable deprecation warnings for "insecure" C library functions
list(APPEND custom_compiler_flags
/GS
/Za
/sdl
/W4
/wd4001
/D_CRT_SECURE_NO_WARNINGS
)
endif()
endif()
option(ENABLE_SANITIZERS "Enables AddressSanitizer and UndefinedBehaviorSanitizer." OFF)
if (ENABLE_SANITIZERS)
list(APPEND custom_compiler_flags
-fno-omit-frame-pointer
-fsanitize=address
-fsanitize=undefined
-fsanitize=float-cast-overflow
-fsanitize-address-use-after-scope
-fsanitize=integer
-01
-fno-sanitize-recover
)
endif()
option(ENABLE_SAFE_STACK "Enables the SafeStack instrumentation pass by the Code Pointer Integrity Project" OFF)
if (ENABLE_SAFE_STACK)
if (ENABLE_SANITIZERS)
message(FATAL_ERROR "ENABLE_SAFE_STACK cannot be used in combination with ENABLE_SANITIZERS")
endif()
list(APPEND custom_compiler_flags
-fsanitize=safe-stack
)
endif()
option(ENABLE_PUBLIC_SYMBOLS "Export library symbols." On)
if (ENABLE_PUBLIC_SYMBOLS)
list(APPEND custom_compiler_flags -fvisibility=hidden)
add_definitions(-DCJSON_EXPORT_SYMBOLS -DCJSON_API_VISIBILITY)
endif()
option(ENABLE_HIDDEN_SYMBOLS "Hide library symbols." Off)
if (ENABLE_HIDDEN_SYMBOLS)
add_definitions(-DCJSON_HIDE_SYMBOLS -UCJSON_API_VISIBILITY)
endif()
# apply custom compiler flags
foreach(compiler_flag ${custom_compiler_flags})
#remove problematic characters
string(REGEX REPLACE "[^a-zA-Z0-9]" "" current_variable ${compiler_flag})
CHECK_C_COMPILER_FLAG(${compiler_flag} "FLAG_SUPPORTED_${current_variable}")
if (FLAG_SUPPORTED_${current_variable})
list(APPEND supported_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_flag}")
endif()
endforeach()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${supported_compiler_flags}")
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(ENABLE_TARGET_EXPORT "Enable exporting of CMake targets. Disable when it causes problems!" ON)
#cJSON
set(CJSON_LIB cjson)
file(GLOB HEADERS cJSON.h)
set(SOURCES cJSON.c)
option(BUILD_SHARED_AND_STATIC_LIBS "Build both shared and static libraries" Off)
option(CJSON_OVERRIDE_BUILD_SHARED_LIBS "Override BUILD_SHARED_LIBS with CJSON_BUILD_SHARED_LIBS" OFF)
option(CJSON_BUILD_SHARED_LIBS "Overrides BUILD_SHARED_LIBS if CJSON_OVERRIDE_BUILD_SHARED_LIBS is enabled" ON)
if ((CJSON_OVERRIDE_BUILD_SHARED_LIBS AND CJSON_BUILD_SHARED_LIBS) OR ((NOT CJSON_OVERRIDE_BUILD_SHARED_LIBS) AND BUILD_SHARED_LIBS))
set(CJSON_LIBRARY_TYPE SHARED)
else()
set(CJSON_LIBRARY_TYPE STATIC)
endif()
if (NOT BUILD_SHARED_AND_STATIC_LIBS)
add_library("${CJSON_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS}" "${SOURCES}")
else()
# See https://cmake.org/Wiki/CMake_FAQ#How_do_I_make_my_shared_and_static_libraries_have_the_same_root_name.2C_but_different_suffixes.3F
add_library("${CJSON_LIB}" SHARED "${HEADERS}" "${SOURCES}")
add_library("${CJSON_LIB}-static" STATIC "${HEADERS}" "${SOURCES}")
set_target_properties("${CJSON_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_LIB}")
set_target_properties("${CJSON_LIB}-static" PROPERTIES PREFIX "lib")
endif()
if (NOT WIN32)
target_link_libraries("${CJSON_LIB}" m)
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" @ONLY)
install(FILES cJSON.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
install(TARGETS "${CJSON_LIB}"
EXPORT "${CJSON_LIB}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
)
if (BUILD_SHARED_AND_STATIC_LIBS)
install(TARGETS "${CJSON_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
if(ENABLE_TARGET_EXPORT)
# export library information for CMake projects
install(EXPORT "${CJSON_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif()
set_target_properties("${CJSON_LIB}"
PROPERTIES
SOVERSION "${CJSON_VERSION_SO}"
VERSION "${PROJECT_VERSION}")
#cJSON_Utils
option(ENABLE_CJSON_UTILS "Enable building the cJSON_Utils library." OFF)
if(ENABLE_CJSON_UTILS)
set(CJSON_UTILS_LIB cjson_utils)
file(GLOB HEADERS_UTILS cJSON_Utils.h)
set(SOURCES_UTILS cJSON_Utils.c)
if (NOT BUILD_SHARED_AND_STATIC_LIBS)
add_library("${CJSON_UTILS_LIB}" "${CJSON_LIBRARY_TYPE}" "${HEADERS_UTILS}" "${SOURCES_UTILS}")
target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}")
else()
add_library("${CJSON_UTILS_LIB}" SHARED "${HEADERS_UTILS}" "${SOURCES_UTILS}")
target_link_libraries("${CJSON_UTILS_LIB}" "${CJSON_LIB}")
add_library("${CJSON_UTILS_LIB}-static" STATIC "${HEADERS_UTILS}" "${SOURCES_UTILS}")
target_link_libraries("${CJSON_UTILS_LIB}-static" "${CJSON_LIB}-static")
set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES OUTPUT_NAME "${CJSON_UTILS_LIB}")
set_target_properties("${CJSON_UTILS_LIB}-static" PROPERTIES PREFIX "lib")
endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/library_config/libcjson_utils.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" @ONLY)
install(TARGETS "${CJSON_UTILS_LIB}"
EXPORT "${CJSON_UTILS_LIB}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}"
)
if (BUILD_SHARED_AND_STATIC_LIBS)
install(TARGETS "${CJSON_UTILS_LIB}-static" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}")
endif()
install(FILES cJSON_Utils.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/cjson")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcjson_utils.pc" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig")
if(ENABLE_TARGET_EXPORT)
# export library information for CMake projects
install(EXPORT "${CJSON_UTILS_LIB}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif()
set_target_properties("${CJSON_UTILS_LIB}"
PROPERTIES
SOVERSION "${CJSON_UTILS_VERSION_SO}"
VERSION "${PROJECT_VERSION}")
endif()
# create the other package config files
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfig.cmake.in"
${PROJECT_BINARY_DIR}/cJSONConfig.cmake @ONLY)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/library_config/cJSONConfigVersion.cmake.in"
${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake @ONLY)
if(ENABLE_TARGET_EXPORT)
# Install package config files
install(FILES ${PROJECT_BINARY_DIR}/cJSONConfig.cmake
${PROJECT_BINARY_DIR}/cJSONConfigVersion.cmake
DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/cmake/cJSON")
endif()
option(ENABLE_CJSON_TEST "Enable building cJSON test" ON)
if(ENABLE_CJSON_TEST)
enable_testing()
set(TEST_CJSON cJSON_test)
add_executable("${TEST_CJSON}" test.c)
target_link_libraries("${TEST_CJSON}" "${CJSON_LIB}")
add_test(NAME ${TEST_CJSON} COMMAND "${CMAKE_CURRENT_BINARY_DIR}/${TEST_CJSON}")
# Disable -fsanitize=float-divide-by-zero for cJSON_test
if (FLAG_SUPPORTED_fsanitizefloatdividebyzero)
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=float-divide-by-zero")
else()
target_compile_options(${TEST_CJSON} PRIVATE "-fno-sanitize=float-divide-by-zero")
endif()
endif()
#"check" target that automatically builds everything and runs the tests
add_custom_target(check
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
DEPENDS ${TEST_CJSON})
endif()
#Create the uninstall target
option(ENABLE_CJSON_UNINSTALL "Enable creating uninstall target" ON)
if(ENABLE_CJSON_UNINSTALL)
add_custom_target(uninstall "${CMAKE_COMMAND}" -P
"${PROJECT_SOURCE_DIR}/library_config/uninstall.cmake")
endif()
# Enable the use of locales
option(ENABLE_LOCALES "Enable the use of locales" ON)
if(ENABLE_LOCALES)
add_definitions(-DENABLE_LOCALES)
endif()
add_subdirectory(tests)
add_subdirectory(fuzzing)

View File

@@ -0,0 +1,79 @@
Contributors
============
Original Author:
- [Dave Gamble](https://github.com/DaveGamble)
Current Maintainer:
- [Max Bruckner](https://github.com/FSMaxB)
- [Alan Wang](https://github.com/Alanscut)
Contributors:
* [Ajay Bhargav](https://github.com/ajaybhargav)
* [Alper Akcan](https://github.com/alperakcan)
* [Andrew Tang](https://github.com/singku)
* [Anton Sergeev](https://github.com/anton-sergeev)
* [Benbuck Nason](https://github.com/bnason-nf)
* [Bernt Johan Damslora](https://github.com/bjda)
* [Bob Kocisko](https://github.com/bobkocisko)
* [Christian Schulze](https://github.com/ChristianSch)
* [Casperinous](https://github.com/Casperinous)
* [ChenYuan](https://github.com/zjuchenyuan)
* [Debora Grosse](https://github.com/DeboraG)
* [dieyushi](https://github.com/dieyushi)
* [Dōngwén Huáng (黄东文)](https://github.com/DongwenHuang)
* [Donough Liu](https://github.com/ldm0)
* [Erez Oxman](https://github.com/erez-o)
* Eswar Yaganti
* [Evan Todd](https://github.com/etodd)
* [Fabrice Fontaine](https://github.com/ffontaine)
* Ian Mobley
* Irwan Djadjadi
* [HuKeping](https://github.com/HuKeping)
* [IvanVoid](https://github.com/npi3pak)
* [Jakub Wilk](https://github.com/jwilk)
* [Jiri Zouhar](https://github.com/loigu)
* [Jonathan Fether](https://github.com/jfether)
* [Julian Ste](https://github.com/julian-st)
* [Julián Vásquez](https://github.com/juvasquezg)
* [Kevin Branigan](https://github.com/kbranigan)
* [Kevin Sapper](https://github.com/sappo)
* [Kyle Chisholm](https://github.com/ChisholmKyle)
* [Linus Wallgren](https://github.com/ecksun)
* [Mateusz Szafoni](https://github.com/raiden00pl)
* Mike Pontillo
* [miaoerduo](https://github.com/miaoerduo)
* [Mike Jerris](https://github.com/mjerris)
* [Mike Robinson](https://github.com/mhrobinson)
* [Moorthy](https://github.com/moorthy-bs)
* [myd7349](https://github.com/myd7349)
* [NancyLi1013](https://github.com/NancyLi1013)
* Paulo Antonio Alvarez
* [Paweł Malowany](https://github.com/PawelMalowany)
* [Pawel Winogrodzki](https://github.com/PawelWMS)
* [prefetchnta](https://github.com/prefetchnta)
* [Rafael Leal Dias](https://github.com/rafaeldias)
* [Randy](https://github.com/randy408)
* [raiden00pl](https://github.com/raiden00pl)
* [Robin Mallinson](https://github.com/rmallins)
* [Rod Vagg](https://github.com/rvagg)
* [Roland Meertens](https://github.com/rmeertens)
* [Romain Porte](https://github.com/MicroJoe)
* [SANJEEV BA](https://github.com/basanjeev)
* [Sang-Heon Jeon](https://github.com/lntuition)
* [Simon Sobisch](https://github.com/GitMensch)
* [Simon Ricaldone](https://github.com/simon-p-r)
* [Square789](https://github.com/Square789)
* [Stephan Gatzka](https://github.com/gatzka)
* [Vemake](https://github.com/vemakereporter)
* [Wei Tan](https://github.com/tan-wei)
* [Weston Schmidt](https://github.com/schmidtw)
* [xiaomianhehe](https://github.com/xiaomianhehe)
* [yangfl](https://github.com/yangfl)
* [yuta-oxo](https://github.com/yuta-oxo)
* [Zach Hindes](https://github.com/zhindes)
* [Zhao Zhixu](https://github.com/zhaozhixu)
And probably more people on [SourceForge](https://sourceforge.net/p/cjson/bugs/search/?q=status%3Aclosed-rejected+or+status%3Aclosed-out-of-date+or+status%3Awont-fix+or+status%3Aclosed-fixed+or+status%3Aclosed&page=0)
Also thanks to all the people who reported bugs and suggested new features.

View File

@@ -0,0 +1,20 @@
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,571 @@
# cJSON
Ultralightweight JSON parser in ANSI C.
## Table of contents
* [License](#license)
* [Usage](#usage)
* [Welcome to cJSON](#welcome-to-cjson)
* [Building](#building)
* [Copying the source](#copying-the-source)
* [CMake](#cmake)
* [Makefile](#makefile)
* [Vcpkg](#Vcpkg)
* [Including cJSON](#including-cjson)
* [Data Structure](#data-structure)
* [Working with the data structure](#working-with-the-data-structure)
* [Basic types](#basic-types)
* [Arrays](#arrays)
* [Objects](#objects)
* [Parsing JSON](#parsing-json)
* [Printing JSON](#printing-json)
* [Example](#example)
* [Printing](#printing)
* [Parsing](#parsing)
* [Caveats](#caveats)
* [Zero Character](#zero-character)
* [Character Encoding](#character-encoding)
* [C Standard](#c-standard)
* [Floating Point Numbers](#floating-point-numbers)
* [Deep Nesting Of Arrays And Objects](#deep-nesting-of-arrays-and-objects)
* [Thread Safety](#thread-safety)
* [Case Sensitivity](#case-sensitivity)
* [Duplicate Object Members](#duplicate-object-members)
* [Enjoy cJSON!](#enjoy-cjson)
## License
MIT License
> Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
## Usage
### Welcome to cJSON.
cJSON aims to be the dumbest possible parser that you can get your job done with.
It's a single file of C, and a single header file.
JSON is described best here: http://www.json.org/
It's like XML, but fat-free. You use it to move data around, store things, or just
generally represent your program's state.
As a library, cJSON exists to take away as much legwork as it can, but not get in your way.
As a point of pragmatism (i.e. ignoring the truth), I'm going to say that you can use it
in one of two modes: Auto and Manual. Let's have a quick run-through.
I lifted some JSON from this page: http://www.json.org/fatfree.html
That page inspired me to write cJSON, which is a parser that tries to share the same
philosophy as JSON itself. Simple, dumb, out of the way.
### Building
There are several ways to incorporate cJSON into your project.
#### copying the source
Because the entire library is only one C file and one header file, you can just copy `cJSON.h` and `cJSON.c` to your projects source and start using it.
cJSON is written in ANSI C (C89) in order to support as many platforms and compilers as possible.
#### CMake
With CMake, cJSON supports a full blown build system. This way you get the most features. CMake with an equal or higher version than 2.8.5 is supported. With CMake it is recommended to do an out of tree build, meaning the compiled files are put in a directory separate from the source files. So in order to build cJSON with CMake on a Unix platform, make a `build` directory and run CMake inside it.
```
mkdir build
cd build
cmake ..
```
This will create a Makefile and a bunch of other files. You can then compile it:
```
make
```
And install it with `make install` if you want. By default it installs the headers `/usr/local/include/cjson` and the libraries to `/usr/local/lib`. It also installs files for pkg-config to make it easier to detect and use an existing installation of CMake. And it installs CMake config files, that can be used by other CMake based projects to discover the library.
You can change the build process with a list of different options that you can pass to CMake. Turn them on with `On` and off with `Off`:
* `-DENABLE_CJSON_TEST=On`: Enable building the tests. (on by default)
* `-DENABLE_CJSON_UTILS=On`: Enable building cJSON_Utils. (off by default)
* `-DENABLE_TARGET_EXPORT=On`: Enable the export of CMake targets. Turn off if it makes problems. (on by default)
* `-DENABLE_CUSTOM_COMPILER_FLAGS=On`: Enable custom compiler flags (currently for Clang, GCC and MSVC). Turn off if it makes problems. (on by default)
* `-DENABLE_VALGRIND=On`: Run tests with [valgrind](http://valgrind.org). (off by default)
* `-DENABLE_SANITIZERS=On`: Compile cJSON with [AddressSanitizer](https://github.com/google/sanitizers/wiki/AddressSanitizer) and [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) enabled (if possible). (off by default)
* `-DENABLE_SAFE_STACK`: Enable the [SafeStack](https://clang.llvm.org/docs/SafeStack.html) instrumentation pass. Currently only works with the Clang compiler. (off by default)
* `-DBUILD_SHARED_LIBS=On`: Build the shared libraries. (on by default)
* `-DBUILD_SHARED_AND_STATIC_LIBS=On`: Build both shared and static libraries. (off by default)
* `-DCMAKE_INSTALL_PREFIX=/usr`: Set a prefix for the installation.
* `-DENABLE_LOCALES=On`: Enable the usage of localeconv method. ( on by default )
* `-DCJSON_OVERRIDE_BUILD_SHARED_LIBS=On`: Enable overriding the value of `BUILD_SHARED_LIBS` with `-DCJSON_BUILD_SHARED_LIBS`.
If you are packaging cJSON for a distribution of Linux, you would probably take these steps for example:
```
mkdir build
cd build
cmake .. -DENABLE_CJSON_UTILS=On -DENABLE_CJSON_TEST=Off -DCMAKE_INSTALL_PREFIX=/usr
make
make DESTDIR=$pkgdir install
```
On Windows CMake is usually used to create a Visual Studio solution file by running it inside the Developer Command Prompt for Visual Studio, for exact steps follow the official documentation from CMake and Microsoft and use the online search engine of your choice. The descriptions of the the options above still generally apply, although not all of them work on Windows.
#### Makefile
**NOTE:** This Method is deprecated. Use CMake if at all possible. Makefile support is limited to fixing bugs.
If you don't have CMake available, but still have GNU make. You can use the makefile to build cJSON:
Run this command in the directory with the source code and it will automatically compile static and shared libraries and a little test program (not the full test suite).
```
make all
```
If you want, you can install the compiled library to your system using `make install`. By default it will install the headers in `/usr/local/include/cjson` and the libraries in `/usr/local/lib`. But you can change this behavior by setting the `PREFIX` and `DESTDIR` variables: `make PREFIX=/usr DESTDIR=temp install`. And uninstall them with: `make PREFIX=/usr DESTDIR=temp uninstall`.
#### Vcpkg
You can download and install cJSON using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
```
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install cjson
```
The cJSON port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
### Including cJSON
If you installed it via CMake or the Makefile, you can include cJSON like this:
```c
#include <cjson/cJSON.h>
```
### Data Structure
cJSON represents JSON data using the `cJSON` struct data type:
```c
/* The cJSON structure: */
typedef struct cJSON
{
struct cJSON *next;
struct cJSON *prev;
struct cJSON *child;
int type;
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
double valuedouble;
char *string;
} cJSON;
```
An item of this type represents a JSON value. The type is stored in `type` as a bit-flag (**this means that you cannot find out the type by just comparing the value of `type`**).
To check the type of an item, use the corresponding `cJSON_Is...` function. It does a `NULL` check followed by a type check and returns a boolean value if the item is of this type.
The type can be one of the following:
* `cJSON_Invalid` (check with `cJSON_IsInvalid`): Represents an invalid item that doesn't contain any value. You automatically have this type if you set the item to all zero bytes.
* `cJSON_False` (check with `cJSON_IsFalse`): Represents a `false` boolean value. You can also check for boolean values in general with `cJSON_IsBool`.
* `cJSON_True` (check with `cJSON_IsTrue`): Represents a `true` boolean value. You can also check for boolean values in general with `cJSON_IsBool`.
* `cJSON_NULL` (check with `cJSON_IsNull`): Represents a `null` value.
* `cJSON_Number` (check with `cJSON_IsNumber`): Represents a number value. The value is stored as a double in `valuedouble` and also in `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint`.
* `cJSON_String` (check with `cJSON_IsString`): Represents a string value. It is stored in the form of a zero terminated string in `valuestring`.
* `cJSON_Array` (check with `cJSON_IsArray`): Represent an array value. This is implemented by pointing `child` to a linked list of `cJSON` items that represent the values in the array. The elements are linked together using `next` and `prev`, where the first element has `prev.next == NULL` and the last element `next == NULL`.
* `cJSON_Object` (check with `cJSON_IsObject`): Represents an object value. Objects are stored same way as an array, the only difference is that the items in the object store their keys in `string`.
* `cJSON_Raw` (check with `cJSON_IsRaw`): Represents any kind of JSON that is stored as a zero terminated array of characters in `valuestring`. This can be used, for example, to avoid printing the same static JSON over and over again to save performance. cJSON will never create this type when parsing. Also note that cJSON doesn't check if it is valid JSON.
Additionally there are the following two flags:
* `cJSON_IsReference`: Specifies that the item that `child` points to and/or `valuestring` is not owned by this item, it is only a reference. So `cJSON_Delete` and other functions will only deallocate this item, not its `child`/`valuestring`.
* `cJSON_StringIsConst`: This means that `string` points to a constant string. This means that `cJSON_Delete` and other functions will not try to deallocate `string`.
### Working with the data structure
For every value type there is a `cJSON_Create...` function that can be used to create an item of that type.
All of these will allocate a `cJSON` struct that can later be deleted with `cJSON_Delete`.
Note that you have to delete them at some point, otherwise you will get a memory leak.
**Important**: If you have added an item to an array or an object already, you **mustn't** delete it with `cJSON_Delete`. Adding it to an array or object transfers its ownership so that when that array or object is deleted,
it gets deleted as well. You also could use `cJSON_SetValuestring` to change a `cJSON_String`'s `valuestring`, and you needn't to free the previous `valuestring` manually.
#### Basic types
* **null** is created with `cJSON_CreateNull`
* **booleans** are created with `cJSON_CreateTrue`, `cJSON_CreateFalse` or `cJSON_CreateBool`
* **numbers** are created with `cJSON_CreateNumber`. This will set both `valuedouble` and `valueint`. If the number is outside of the range of an integer, `INT_MAX` or `INT_MIN` are used for `valueint`
* **strings** are created with `cJSON_CreateString` (copies the string) or with `cJSON_CreateStringReference` (directly points to the string. This means that `valuestring` won't be deleted by `cJSON_Delete` and you are responsible for its lifetime, useful for constants)
#### Arrays
You can create an empty array with `cJSON_CreateArray`. `cJSON_CreateArrayReference` can be used to create an array that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`.
To add items to an array, use `cJSON_AddItemToArray` to append items to the end.
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another item, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occurring if they are already used elsewhere.
To insert items in the middle, use `cJSON_InsertItemInArray`. It will insert an item at the given 0 based index and shift all the existing items to the right.
If you want to take an item out of an array at a given index and continue using it, use `cJSON_DetachItemFromArray`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.
Deleting items is done with `cJSON_DeleteItemFromArray`. It works like `cJSON_DetachItemFromArray`, but deletes the detached item via `cJSON_Delete`.
You can also replace an item in an array in place. Either with `cJSON_ReplaceItemInArray` using an index or with `cJSON_ReplaceItemViaPointer` given a pointer to an element. `cJSON_ReplaceItemViaPointer` will return `0` if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place.
To get the size of an array, use `cJSON_GetArraySize`. Use `cJSON_GetArrayItem` to get an element at a given index.
Because an array is stored as a linked list, iterating it via index is inefficient (`O(n²)`), so you can iterate over an array using the `cJSON_ArrayForEach` macro in `O(n)` time complexity.
#### Objects
You can create an empty object with `cJSON_CreateObject`. `cJSON_CreateObjectReference` can be used to create an object that doesn't "own" its content, so its content doesn't get deleted by `cJSON_Delete`.
To add items to an object, use `cJSON_AddItemToObject`. Use `cJSON_AddItemToObjectCS` to add an item to an object with a name that is a constant or reference (key of the item, `string` in the `cJSON` struct), so that it doesn't get freed by `cJSON_Delete`.
Using `cJSON_AddItemReferenceToArray` an element can be added as a reference to another object, array or string. This means that `cJSON_Delete` will not delete that items `child` or `valuestring` properties, so no double frees are occurring if they are already used elsewhere.
If you want to take an item out of an object, use `cJSON_DetachItemFromObjectCaseSensitive`, it will return the detached item, so be sure to assign it to a pointer, otherwise you will have a memory leak.
Deleting items is done with `cJSON_DeleteItemFromObjectCaseSensitive`. It works like `cJSON_DetachItemFromObjectCaseSensitive` followed by `cJSON_Delete`.
You can also replace an item in an object in place. Either with `cJSON_ReplaceItemInObjectCaseSensitive` using a key or with `cJSON_ReplaceItemViaPointer` given a pointer to an element. `cJSON_ReplaceItemViaPointer` will return `0` if it fails. What this does internally is to detach the old item, delete it and insert the new item in its place.
To get the size of an object, you can use `cJSON_GetArraySize`, this works because internally objects are stored as arrays.
If you want to access an item in an object, use `cJSON_GetObjectItemCaseSensitive`.
To iterate over an object, you can use the `cJSON_ArrayForEach` macro the same way as for arrays.
cJSON also provides convenient helper functions for quickly creating a new item and adding it to an object, like `cJSON_AddNullToObject`. They return a pointer to the new item or `NULL` if they failed.
### Parsing JSON
Given some JSON in a zero terminated string, you can parse it with `cJSON_Parse`.
```c
cJSON *json = cJSON_Parse(string);
```
Given some JSON in a string (whether zero terminated or not), you can parse it with `cJSON_ParseWithLength`.
```c
cJSON *json = cJSON_ParseWithLength(string, buffer_length);
```
It will parse the JSON and allocate a tree of `cJSON` items that represents it. Once it returns, you are fully responsible for deallocating it after use with `cJSON_Delete`.
The allocator used by `cJSON_Parse` is `malloc` and `free` by default but can be changed (globally) with `cJSON_InitHooks`.
If an error occurs a pointer to the position of the error in the input string can be accessed using `cJSON_GetErrorPtr`. Note though that this can produce race conditions in multithreading scenarios, in that case it is better to use `cJSON_ParseWithOpts` with `return_parse_end`.
By default, characters in the input string that follow the parsed JSON will not be considered as an error.
If you want more options, use `cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)`.
`return_parse_end` returns a pointer to the end of the JSON in the input string or the position that an error occurs at (thereby replacing `cJSON_GetErrorPtr` in a thread safe way). `require_null_terminated`, if set to `1` will make it an error if the input string contains data after the JSON.
If you want more options giving buffer length, use `cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)`.
### Printing JSON
Given a tree of `cJSON` items, you can print them as a string using `cJSON_Print`.
```c
char *string = cJSON_Print(json);
```
It will allocate a string and print a JSON representation of the tree into it. Once it returns, you are fully responsible for deallocating it after use with your allocator. (usually `free`, depends on what has been set with `cJSON_InitHooks`).
`cJSON_Print` will print with whitespace for formatting. If you want to print without formatting, use `cJSON_PrintUnformatted`.
If you have a rough idea of how big your resulting string will be, you can use `cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)`. `fmt` is a boolean to turn formatting with whitespace on and off. `prebuffer` specifies the first buffer size to use for printing. `cJSON_Print` currently uses 256 bytes for its first buffer size. Once printing runs out of space, a new buffer is allocated and the old gets copied over before printing is continued.
These dynamic buffer allocations can be completely avoided by using `cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)`. It takes a buffer to a pointer to print to and its length. If the length is reached, printing will fail and it returns `0`. In case of success, `1` is returned. Note that you should provide 5 bytes more than is actually needed, because cJSON is not 100% accurate in estimating if the provided memory is enough.
### Example
In this example we want to build and parse the following JSON:
```json
{
"name": "Awesome 4K",
"resolutions": [
{
"width": 1280,
"height": 720
},
{
"width": 1920,
"height": 1080
},
{
"width": 3840,
"height": 2160
}
]
}
```
#### Printing
Let's build the above JSON and print it to a string:
```c
//create a monitor with a list of supported resolutions
//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *name = NULL;
cJSON *resolutions = NULL;
cJSON *resolution = NULL;
cJSON *width = NULL;
cJSON *height = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (monitor == NULL)
{
goto end;
}
name = cJSON_CreateString("Awesome 4K");
if (name == NULL)
{
goto end;
}
/* after creation was successful, immediately add it to the monitor,
* thereby transferring ownership of the pointer to it */
cJSON_AddItemToObject(monitor, "name", name);
resolutions = cJSON_CreateArray();
if (resolutions == NULL)
{
goto end;
}
cJSON_AddItemToObject(monitor, "resolutions", resolutions);
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
resolution = cJSON_CreateObject();
if (resolution == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
width = cJSON_CreateNumber(resolution_numbers[index][0]);
if (width == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "width", width);
height = cJSON_CreateNumber(resolution_numbers[index][1]);
if (height == NULL)
{
goto end;
}
cJSON_AddItemToObject(resolution, "height", height);
}
string = cJSON_Print(monitor);
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
```
Alternatively we can use the `cJSON_Add...ToObject` helper functions to make our lifes a little easier:
```c
//NOTE: Returns a heap allocated string, you are required to free it after use.
char *create_monitor_with_helpers(void)
{
const unsigned int resolution_numbers[3][2] = {
{1280, 720},
{1920, 1080},
{3840, 2160}
};
char *string = NULL;
cJSON *resolutions = NULL;
size_t index = 0;
cJSON *monitor = cJSON_CreateObject();
if (cJSON_AddStringToObject(monitor, "name", "Awesome 4K") == NULL)
{
goto end;
}
resolutions = cJSON_AddArrayToObject(monitor, "resolutions");
if (resolutions == NULL)
{
goto end;
}
for (index = 0; index < (sizeof(resolution_numbers) / (2 * sizeof(int))); ++index)
{
cJSON *resolution = cJSON_CreateObject();
if (cJSON_AddNumberToObject(resolution, "width", resolution_numbers[index][0]) == NULL)
{
goto end;
}
if (cJSON_AddNumberToObject(resolution, "height", resolution_numbers[index][1]) == NULL)
{
goto end;
}
cJSON_AddItemToArray(resolutions, resolution);
}
string = cJSON_Print(monitor);
if (string == NULL)
{
fprintf(stderr, "Failed to print monitor.\n");
}
end:
cJSON_Delete(monitor);
return string;
}
```
#### Parsing
In this example we will parse a JSON in the above format and check if the monitor supports a Full HD resolution while printing some diagnostic output:
```c
/* return 1 if the monitor supports full hd, 0 otherwise */
int supports_full_hd(const char * const monitor)
{
const cJSON *resolution = NULL;
const cJSON *resolutions = NULL;
const cJSON *name = NULL;
int status = 0;
cJSON *monitor_json = cJSON_Parse(monitor);
if (monitor_json == NULL)
{
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL)
{
fprintf(stderr, "Error before: %s\n", error_ptr);
}
status = 0;
goto end;
}
name = cJSON_GetObjectItemCaseSensitive(monitor_json, "name");
if (cJSON_IsString(name) && (name->valuestring != NULL))
{
printf("Checking monitor \"%s\"\n", name->valuestring);
}
resolutions = cJSON_GetObjectItemCaseSensitive(monitor_json, "resolutions");
cJSON_ArrayForEach(resolution, resolutions)
{
cJSON *width = cJSON_GetObjectItemCaseSensitive(resolution, "width");
cJSON *height = cJSON_GetObjectItemCaseSensitive(resolution, "height");
if (!cJSON_IsNumber(width) || !cJSON_IsNumber(height))
{
status = 0;
goto end;
}
if ((width->valuedouble == 1920) && (height->valuedouble == 1080))
{
status = 1;
goto end;
}
}
end:
cJSON_Delete(monitor_json);
return status;
}
```
Note that there are no NULL checks except for the result of `cJSON_Parse` because `cJSON_GetObjectItemCaseSensitive` checks for `NULL` inputs already, so a `NULL` value is just propagated and `cJSON_IsNumber` and `cJSON_IsString` return `0` if the input is `NULL`.
### Caveats
#### Zero Character
cJSON doesn't support strings that contain the zero character `'\0'` or `\u0000`. This is impossible with the current API because strings are zero terminated.
#### Character Encoding
cJSON only supports UTF-8 encoded input. In most cases it doesn't reject invalid UTF-8 as input though, it just propagates it through as is. As long as the input doesn't contain invalid UTF-8, the output will always be valid UTF-8.
#### C Standard
cJSON is written in ANSI C (or C89, C90). If your compiler or C library doesn't follow this standard, correct behavior is not guaranteed.
NOTE: ANSI C is not C++ therefore it shouldn't be compiled with a C++ compiler. You can compile it with a C compiler and link it with your C++ code however. Although compiling with a C++ compiler might work, correct behavior is not guaranteed.
#### Floating Point Numbers
cJSON does not officially support any `double` implementations other than IEEE754 double precision floating point numbers. It might still work with other implementations but bugs with these will be considered invalid.
The maximum length of a floating point literal that cJSON supports is currently 63 characters.
#### Deep Nesting Of Arrays And Objects
cJSON doesn't support arrays and objects that are nested too deeply because this would result in a stack overflow. To prevent this cJSON limits the depth to `CJSON_NESTING_LIMIT` which is 1000 by default but can be changed at compile time.
#### Thread Safety
In general cJSON is **not thread safe**.
However it is thread safe under the following conditions:
* `cJSON_GetErrorPtr` is never used (the `return_parse_end` parameter of `cJSON_ParseWithOpts` can be used instead)
* `cJSON_InitHooks` is only ever called before using cJSON in any threads.
* `setlocale` is never called before all calls to cJSON functions have returned.
#### Case Sensitivity
When cJSON was originally created, it didn't follow the JSON standard and didn't make a distinction between uppercase and lowercase letters. If you want the correct, standard compliant, behavior, you need to use the `CaseSensitive` functions where available.
#### Duplicate Object Members
cJSON supports parsing and printing JSON that contains objects that have multiple members with the same name. `cJSON_GetObjectItemCaseSensitive` however will always only return the first one.
# Enjoy cJSON!
- Dave Gamble (original author)
- Max Bruckner and Alan Wang (current maintainer)
- and the other [cJSON contributors](CONTRIBUTORS.md)

View File

@@ -0,0 +1,86 @@
os: Visual Studio 2015
# ENABLE_CUSTOM_COMPILER_FLAGS - on by default
# ENABLE_SANITIZERS - off by default
# ENABLE_PUBLIC_SYMBOLS - on by default
# BUILD_SHARED_LIBS - on by default
# ENABLE_TARGET_EXPORT - on by default
# ENABLE_CJSON_UTILS - off by default
# ENABLE_CJSON_TEST -on by default
# ENABLE_VALGRIND - off by default
# ENABLE_FUZZING - off by default
environment:
matrix:
- GENERATOR: "Visual Studio 14 2015"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 14 2015"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 12 2013"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 12 2013"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 11 2012"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 11 2012"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 10 2010"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 10 2010"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 9 2008"
BUILD_SHARED_LIBS: ON
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
- GENERATOR: "Visual Studio 9 2008"
BUILD_SHARED_LIBS: OFF
ENABLE_CJSON_TEST: OFF
ENABLE_CJSON_UTILS: ON
platform:
- x86
- x64
matrix:
exclude:
- platform: x64
GENERATOR: "Visual Studio 9 2008"
configuration:
- Release
build_script:
- ps: if($env:PLATFORM -eq "x64") { $env:CMAKE_GEN_SUFFIX=" Win64" }
- cmake "-G%GENERATOR%%CMAKE_GEN_SUFFIX%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% -DENABLE_CJSON_TEST=%ENABLE_CJSON_TEST% -H. -Bbuild
- cmake --build build --config "%CONFIGURATION%"
on_failure:
- ps: if(Test-Path builds/CMakeFiles/CMakeOutput.log) { cat builds/CMakeFiles/CMakeOutput.log }
- ps: if(Test-Path builds/CMakeFiles/CMakeError.log) { cat builds/CMakeFiles/CMakeError.log }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,293 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 15
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON_Utils__h
#define cJSON_Utils__h
#ifdef __cplusplus
extern "C"
{
#endif
#include "cJSON.h"
/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */
CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointer(cJSON * const object, const char *pointer);
CJSON_PUBLIC(cJSON *) cJSONUtils_GetPointerCaseSensitive(cJSON * const object, const char *pointer);
/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */
/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */
CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatches(cJSON * const from, cJSON * const to);
CJSON_PUBLIC(cJSON *) cJSONUtils_GeneratePatchesCaseSensitive(cJSON * const from, cJSON * const to);
/* Utility for generating patch array entries. */
CJSON_PUBLIC(void) cJSONUtils_AddPatchToArray(cJSON * const array, const char * const operation, const char * const path, const cJSON * const value);
/* Returns 0 for success. */
CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * const patches);
CJSON_PUBLIC(int) cJSONUtils_ApplyPatchesCaseSensitive(cJSON * const object, const cJSON * const patches);
/*
// Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use:
//int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches)
//{
// cJSON *modme = cJSON_Duplicate(*object, 1);
// int error = cJSONUtils_ApplyPatches(modme, patches);
// if (!error)
// {
// cJSON_Delete(*object);
// *object = modme;
// }
// else
// {
// cJSON_Delete(modme);
// }
//
// return error;
//}
// Code not added to library since this strategy is a LOT slower.
*/
/* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */
/* target will be modified by patch. return value is new ptr for target. */
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch);
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatchCaseSensitive(cJSON *target, const cJSON * const patch);
/* generates a patch to move from -> to */
/* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to);
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatchCaseSensitive(cJSON * const from, cJSON * const to);
/* Given a root object and a target object, construct a pointer from one to the other. */
CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target);
/* Sorts the members of the object into alphabetical order. */
CJSON_PUBLIC(void) cJSONUtils_SortObject(cJSON * const object);
CJSON_PUBLIC(void) cJSONUtils_SortObjectCaseSensitive(cJSON * const object);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1 @@
afl-build

View File

@@ -0,0 +1,34 @@
option(ENABLE_FUZZING "Create executables and targets for fuzzing cJSON with afl." Off)
if (ENABLE_FUZZING)
find_program(AFL_FUZZ afl-fuzz)
if ("${AFL_FUZZ}" MATCHES "AFL_FUZZ-NOTFOUND")
message(FATAL_ERROR "Couldn't find afl-fuzz.")
endif()
add_executable(afl-main afl.c)
target_link_libraries(afl-main "${CJSON_LIB}")
if (NOT ENABLE_SANITIZERS)
message(FATAL_ERROR "Enable sanitizers with -DENABLE_SANITIZERS=On to do fuzzing.")
endif()
option(ENABLE_FUZZING_PRINT "Fuzz printing functions together with parser." On)
set(fuzz_print_parameter "no")
if (ENABLE_FUZZING_PRINT)
set(fuzz_print_parameter "yes")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error")
add_custom_target(afl
COMMAND "${AFL_FUZZ}" -i "${CMAKE_CURRENT_SOURCE_DIR}/inputs" -o "${CMAKE_CURRENT_BINARY_DIR}/findings" -x "${CMAKE_CURRENT_SOURCE_DIR}/json.dict" -- "${CMAKE_CURRENT_BINARY_DIR}/afl-main" "@@" "${fuzz_print_parameter}"
DEPENDS afl-main)
endif()
if(ENABLE_CJSON_TEST)
ADD_EXECUTABLE(fuzz_main fuzz_main.c cjson_read_fuzzer.c)
TARGET_LINK_LIBRARIES(fuzz_main cjson)
endif()

View File

@@ -0,0 +1,5 @@
#!/bin/bash
set -x
echo core | sudo tee /proc/sys/kernel/core_pattern
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

View File

@@ -0,0 +1,176 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../cJSON.h"
static char *read_file(const char *filename)
{
FILE *file = NULL;
long length = 0;
char *content = NULL;
size_t read_chars = 0;
/* open in read binary mode */
file = fopen(filename, "rb");
if (file == NULL)
{
goto cleanup;
}
/* get the length */
if (fseek(file, 0, SEEK_END) != 0)
{
goto cleanup;
}
length = ftell(file);
if (length < 0)
{
goto cleanup;
}
if (fseek(file, 0, SEEK_SET) != 0)
{
goto cleanup;
}
/* allocate content buffer */
content = (char*)malloc((size_t)length + sizeof(""));
if (content == NULL)
{
goto cleanup;
}
/* read the file into memory */
read_chars = fread(content, sizeof(char), (size_t)length, file);
if ((long)read_chars != length)
{
free(content);
content = NULL;
goto cleanup;
}
content[read_chars] = '\0';
cleanup:
if (file != NULL)
{
fclose(file);
}
return content;
}
int main(int argc, char** argv)
{
const char *filename = NULL;
cJSON *item = NULL;
char *json = NULL;
int status = EXIT_FAILURE;
char *printed_json = NULL;
if ((argc < 2) || (argc > 3))
{
printf("Usage:\n");
printf("%s input_file [enable_printing]\n", argv[0]);
printf("\t input_file: file containing the test data\n");
printf("\t enable_printing: print after parsing, 'yes' or 'no', defaults to 'no'\n");
goto cleanup;
}
filename = argv[1];
#if __AFL_HAVE_MANUAL_CONTROL
while (__AFL_LOOP(1000))
{
#endif
status = EXIT_SUCCESS;
json = read_file(filename);
if ((json == NULL) || (json[0] == '\0') || (json[1] == '\0'))
{
status = EXIT_FAILURE;
goto cleanup;
}
item = cJSON_Parse(json + 2);
if (item == NULL)
{
goto cleanup;
}
if ((argc == 3) && (strncmp(argv[2], "yes", 3) == 0))
{
int do_format = 0;
if (json[1] == 'f')
{
do_format = 1;
}
if (json[0] == 'b')
{
/* buffered printing */
printed_json = cJSON_PrintBuffered(item, 1, do_format);
}
else
{
/* unbuffered printing */
if (do_format)
{
printed_json = cJSON_Print(item);
}
else
{
printed_json = cJSON_PrintUnformatted(item);
}
}
if (printed_json == NULL)
{
status = EXIT_FAILURE;
goto cleanup;
}
printf("%s\n", printed_json);
}
cleanup:
if (item != NULL)
{
cJSON_Delete(item);
item = NULL;
}
if (json != NULL)
{
free(json);
json = NULL;
}
if (printed_json != NULL)
{
free(printed_json);
printed_json = NULL;
}
#if __AFL_HAVE_MANUAL_CONTROL
}
#endif
return status;
}

View File

@@ -0,0 +1,9 @@
#!/bin/bash
mkdir -p afl-build || exit 1
cd afl-build || exit 1
#cleanup
rm -r -- *
CC=afl-clang-fast cmake ../.. -DENABLE_FUZZING=On -DENABLE_SANITIZERS=On -DBUILD_SHARED_LIBS=Off
make afl

View File

@@ -0,0 +1,77 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "../cJSON.h"
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
cJSON *json;
size_t offset = 4;
unsigned char *copied;
char *printed_json = NULL;
int minify, require_termination, formatted, buffered;
if(size <= offset) return 0;
if(data[size-1] != '\0') return 0;
if(data[0] != '1' && data[0] != '0') return 0;
if(data[1] != '1' && data[1] != '0') return 0;
if(data[2] != '1' && data[2] != '0') return 0;
if(data[3] != '1' && data[3] != '0') return 0;
minify = data[0] == '1' ? 1 : 0;
require_termination = data[1] == '1' ? 1 : 0;
formatted = data[2] == '1' ? 1 : 0;
buffered = data[3] == '1' ? 1 : 0;
json = cJSON_ParseWithOpts((const char*)data + offset, NULL, require_termination);
if(json == NULL) return 0;
if(buffered)
{
printed_json = cJSON_PrintBuffered(json, 1, formatted);
}
else
{
/* unbuffered printing */
if(formatted)
{
printed_json = cJSON_Print(json);
}
else
{
printed_json = cJSON_PrintUnformatted(json);
}
}
if(printed_json != NULL) free(printed_json);
if(minify)
{
copied = (unsigned char*)malloc(size);
if(copied == NULL) return 0;
memcpy(copied, data, size);
cJSON_Minify((char*)copied + offset);
free(copied);
}
cJSON_Delete(json);
return 0;
}
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,54 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size); /* required by C89 */
/* fuzz target entry point, works without libFuzzer */
int main(int argc, char **argv)
{
FILE *f;
char *buf = NULL;
long siz_buf;
if(argc < 2)
{
fprintf(stderr, "no input file\n");
goto err;
}
f = fopen(argv[1], "rb");
if(f == NULL)
{
fprintf(stderr, "error opening input file %s\n", argv[1]);
goto err;
}
fseek(f, 0, SEEK_END);
siz_buf = ftell(f);
rewind(f);
if(siz_buf < 1) goto err;
buf = (char*)malloc((size_t)siz_buf);
if(buf == NULL)
{
fprintf(stderr, "malloc() failed\n");
goto err;
}
if(fread(buf, (size_t)siz_buf, 1, f) != 1)
{
fprintf(stderr, "fread() failed\n");
goto err;
}
(void)LLVMFuzzerTestOneInput((uint8_t*)buf, (size_t)siz_buf);
err:
free(buf);
return 0;
}

View File

@@ -0,0 +1,22 @@
bf{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}

View File

@@ -0,0 +1 @@
bf["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

View File

@@ -0,0 +1,8 @@
bf{
"name": "Jack (\"Bee\") Nimble",
"format": {"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,"frame rate": 24
}
}

View File

@@ -0,0 +1,11 @@
bf{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}

View File

@@ -0,0 +1,26 @@
bf{"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}

View File

@@ -0,0 +1,26 @@
bu{"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}

View File

@@ -0,0 +1,26 @@
uf{"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}

View File

@@ -0,0 +1,26 @@
uu{"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}

View File

@@ -0,0 +1,88 @@
bf{"web-app": {
"servlet": [
{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
"init-param": {
"configGlossary:installationAt": "Philadelphia, PA",
"configGlossary:adminEmail": "ksm@pobox.com",
"configGlossary:poweredBy": "Cofax",
"configGlossary:poweredByIcon": "/images/cofax.gif",
"configGlossary:staticPath": "/content/static",
"templateProcessorClass": "org.cofax.WysiwygTemplate",
"templateLoaderClass": "org.cofax.FilesTemplateLoader",
"templatePath": "templates",
"templateOverridePath": "",
"defaultListTemplate": "listTemplate.htm",
"defaultFileTemplate": "articleTemplate.htm",
"useJSP": false,
"jspListTemplate": "listTemplate.jsp",
"jspFileTemplate": "articleTemplate.jsp",
"cachePackageTagsTrack": 200,
"cachePackageTagsStore": 200,
"cachePackageTagsRefresh": 60,
"cacheTemplatesTrack": 100,
"cacheTemplatesStore": 50,
"cacheTemplatesRefresh": 15,
"cachePagesTrack": 200,
"cachePagesStore": 100,
"cachePagesRefresh": 10,
"cachePagesDirtyRead": 10,
"searchEngineListTemplate": "forSearchEnginesList.htm",
"searchEngineFileTemplate": "forSearchEngines.htm",
"searchEngineRobotsDb": "WEB-INF/robots.db",
"useDataStore": true,
"dataStoreClass": "org.cofax.SqlDataStore",
"redirectionClass": "org.cofax.SqlRedirection",
"dataStoreName": "cofax",
"dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
"dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
"dataStoreUser": "sa",
"dataStorePassword": "dataStoreTestQuery",
"dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
"dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
"dataStoreInitConns": 10,
"dataStoreMaxConns": 100,
"dataStoreConnUsageLimit": 100,
"dataStoreLogLevel": "debug",
"maxUrlLength": 500}},
{
"servlet-name": "cofaxEmail",
"servlet-class": "org.cofax.cds.EmailServlet",
"init-param": {
"mailHost": "mail1",
"mailHostOverride": "mail2"}},
{
"servlet-name": "cofaxAdmin",
"servlet-class": "org.cofax.cds.AdminServlet"},
{
"servlet-name": "fileServlet",
"servlet-class": "org.cofax.cds.FileServlet"},
{
"servlet-name": "cofaxTools",
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
"init-param": {
"templatePath": "toolstemplates/",
"log": 1,
"logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
"logMaxSize": "",
"dataLog": 1,
"dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
"dataLogMaxSize": "",
"removePageCache": "/content/admin/remove?cache=pages&id=",
"removeTemplateCache": "/content/admin/remove?cache=templates&id=",
"fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
"lookInContext": 1,
"adminGroupID": 4,
"betaServer": true}}],
"servlet-mapping": {
"cofaxCDS": "/",
"cofaxEmail": "/cofaxutil/aemail/*",
"cofaxAdmin": "/admin/*",
"fileServlet": "/static/*",
"cofaxTools": "/tools/*"},
"taglib": {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"}}}

View File

@@ -0,0 +1,27 @@
bf{"menu": {
"header": "SVG Viewer",
"items": [
{"id": "Open"},
{"id": "OpenNew", "label": "Open New"},
null,
{"id": "ZoomIn", "label": "Zoom In"},
{"id": "ZoomOut", "label": "Zoom Out"},
{"id": "OriginalView", "label": "Original View"},
null,
{"id": "Quality"},
{"id": "Pause"},
{"id": "Mute"},
null,
{"id": "Find", "label": "Find..."},
{"id": "FindAgain", "label": "Find Again"},
{"id": "Copy"},
{"id": "CopyAgain", "label": "Copy Again"},
{"id": "CopySVG", "label": "Copy SVG"},
{"id": "ViewSVG", "label": "View SVG"},
{"id": "ViewSource", "label": "View Source"},
{"id": "SaveAs", "label": "Save As"},
null,
{"id": "Help"},
{"id": "About", "label": "About Adobe CVG Viewer..."}
]
}}

View File

@@ -0,0 +1,16 @@
bf<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
html, body, iframe { margin: 0; padding: 0; height: 100%; }
iframe { display: block; width: 100%; border: none; }
</style>
<title>Application Error</title>
</head>
<body>
<iframe src="//s3.amazonaws.com/heroku_pages/error.html">
<p>Application Error</p>
</iframe>
</body>
</html>

View File

@@ -0,0 +1,22 @@
bf[
{
"precision": "zip",
"Latitude": 37.7668,
"Longitude": -122.3959,
"Address": "",
"City": "SAN FRANCISCO",
"State": "CA",
"Zip": "94107",
"Country": "US"
},
{
"precision": "zip",
"Latitude": 37.371991,
"Longitude": -122.026020,
"Address": "",
"City": "SUNNYVALE",
"State": "CA",
"Zip": "94085",
"Country": "US"
}
]

View File

@@ -0,0 +1,13 @@
bf{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http:/*www.example.com/image/481989943",
"Height": 125,
"Width": "100"
},
"IDs": [116, 943, 234, 38793]
}
}

View File

@@ -0,0 +1,5 @@
bf[
[0, -1, 0],
[1, 0, 0],
[0, 0, 1]
]

View File

@@ -0,0 +1,47 @@
#
# AFL dictionary for JSON
# -----------------------------
#
object_start="{"
object_end="}"
object_empty="{}"
object_one_element="{\"one\":1}"
object_two_elements="{\"1\":1,\"2\":2}"
object_separator=":"
array_start="["
array_end="]"
array_empty="[]"
array_one_element="[1]"
array_two_elements="[1,2]"
separator=","
escape_sequence_b="\\b"
escape_sequence_f="\\f"
escape_sequence_n="\\n"
escape_sequence_r="\\r"
escape_sequence_t="\\t"
escape_sequence_quote="\\\""
escape_sequence_backslash="\\\\"
escape_sequence_slash="\\/"
escape_sequence_utf16_base="\\u"
escape_sequence_utf16="\\u12ab"
number_integer="1"
number_double="1.0"
number_negative_integer="-1"
number_negative_double="-1.0"
number_engineering1="1e1"
number_engineering2="1e-1"
number_positive_integer="+1"
number_positive_double="+1.0"
number_e="e"
number_plus="+"
number_minus="-"
number_separator="."
null="null"
true="true"
false="false"

View File

@@ -0,0 +1,18 @@
#!/bin/bash -eu
# This script is meant to be run by
# https://github.com/google/oss-fuzz/blob/master/projects/cjson/Dockerfile
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=OFF -DENABLE_CJSON_TEST=OFF ..
make -j$(nproc)
$CXX $CXXFLAGS $SRC/cjson/fuzzing/cjson_read_fuzzer.c -I. \
-o $OUT/cjson_read_fuzzer \
$LIB_FUZZING_ENGINE $SRC/cjson/build/libcjson.a
find $SRC/cjson/fuzzing/inputs -name "*" | \
xargs zip $OUT/cjson_read_fuzzer_seed_corpus.zip
cp $SRC/cjson/fuzzing/json.dict $OUT/cjson_read_fuzzer.dict

View File

@@ -0,0 +1,29 @@
# Whether the utils lib was build.
set(CJSON_UTILS_FOUND @ENABLE_CJSON_UTILS@)
# The include directories used by cJSON
set(CJSON_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
set(CJSON_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
get_filename_component(_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
# The cJSON library
set(CJSON_LIBRARY "@CJSON_LIB@")
if(@ENABLE_TARGET_EXPORT@)
# Include the target
include("${_dir}/cjson.cmake")
endif()
if(CJSON_UTILS_FOUND)
# The cJSON utils library
set(CJSON_UTILS_LIBRARY @CJSON_UTILS_LIB@)
# All cJSON libraries
set(CJSON_LIBRARIES "@CJSON_UTILS_LIB@" "@CJSON_LIB@")
if(@ENABLE_TARGET_EXPORT@)
# Include the target
include("${_dir}/cjson_utils.cmake")
endif()
else()
# All cJSON libraries
set(CJSON_LIBRARIES "@CJSON_LIB@")
endif()

View File

@@ -0,0 +1,11 @@
set(PACKAGE_VERSION "@PROJECT_VERSION@")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()

View File

@@ -0,0 +1,10 @@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: libcjson
Version: @PROJECT_VERSION@
Description: Ultralightweight JSON parser in ANSI C
URL: https://github.com/DaveGamble/cJSON
Libs: -L${libdir} -lcjson
Libs.private: -lm
Cflags: -I${includedir} -I${includedir}/cjson

View File

@@ -0,0 +1,10 @@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: libcjson_utils
Version: @PROJECT_VERSION@
Description: An implementation of JSON Pointer, Patch and Merge Patch based on cJSON.
URL: https://github.com/DaveGamble/cJSON
Libs: -L${libdir} -lcjson_utils
Cflags: -I${includedir} -I${includedir}/cjson
Requires: libcjson

View File

@@ -0,0 +1,27 @@
cmake_minimum_required(VERSION 2.8.5)
set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt")
if(NOT EXISTS ${MANIFEST})
message(FATAL_ERROR "Cannot find install mainfest: ${MANIFEST}")
endif()
file(STRINGS ${MANIFEST} files)
foreach(file ${files})
if(EXISTS ${file} OR IS_SYMLINK ${file})
message(STATUS "Removing: ${file}")
execute_process(COMMAND rm -f ${file}
RESULT_VARIABLE result
OUTPUT_QUIET
ERROR_VARIABLE stderr
ERROR_STRIP_TRAILING_WHITESPACE
)
if(NOT ${result} EQUAL 0)
message(FATAL_ERROR "${stderr}")
endif()
else()
message(STATUS "Does-not-exist: ${file}")
endif()
endforeach(file)

View File

@@ -0,0 +1,268 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
/* Used by some code below as an example datatype. */
struct record
{
const char *precision;
double lat;
double lon;
const char *address;
const char *city;
const char *state;
const char *zip;
const char *country;
};
/* Create a bunch of objects as demonstration. */
static int print_preallocated(cJSON *root)
{
/* declarations */
char *out = NULL;
char *buf = NULL;
char *buf_fail = NULL;
size_t len = 0;
size_t len_fail = 0;
/* formatted print */
out = cJSON_Print(root);
/* create buffer to succeed */
/* the extra 5 bytes are because of inaccuracies when reserving memory */
len = strlen(out) + 5;
buf = (char*)malloc(len);
if (buf == NULL)
{
printf("Failed to allocate memory.\n");
exit(1);
}
/* create buffer to fail */
len_fail = strlen(out);
buf_fail = (char*)malloc(len_fail);
if (buf_fail == NULL)
{
printf("Failed to allocate memory.\n");
exit(1);
}
/* Print to buffer */
if (!cJSON_PrintPreallocated(root, buf, (int)len, 1)) {
printf("cJSON_PrintPreallocated failed!\n");
if (strcmp(out, buf) != 0) {
printf("cJSON_PrintPreallocated not the same as cJSON_Print!\n");
printf("cJSON_Print result:\n%s\n", out);
printf("cJSON_PrintPreallocated result:\n%s\n", buf);
}
free(out);
free(buf_fail);
free(buf);
return -1;
}
/* success */
printf("%s\n", buf);
/* force it to fail */
if (cJSON_PrintPreallocated(root, buf_fail, (int)len_fail, 1)) {
printf("cJSON_PrintPreallocated failed to show error with insufficient memory!\n");
printf("cJSON_Print result:\n%s\n", out);
printf("cJSON_PrintPreallocated result:\n%s\n", buf_fail);
free(out);
free(buf_fail);
free(buf);
return -1;
}
free(out);
free(buf_fail);
free(buf);
return 0;
}
/* Create a bunch of objects as demonstration. */
static void create_objects(void)
{
/* declare a few. */
cJSON *root = NULL;
cJSON *fmt = NULL;
cJSON *img = NULL;
cJSON *thm = NULL;
cJSON *fld = NULL;
int i = 0;
/* Our "days of the week" array: */
const char *strings[7] =
{
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
/* Our matrix: */
int numbers[3][3] =
{
{0, -1, 0},
{1, 0, 0},
{0 ,0, 1}
};
/* Our "gallery" item: */
int ids[4] = { 116, 943, 234, 38793 };
/* Our array of "records": */
struct record fields[2] =
{
{
"zip",
37.7668,
-1.223959e+2,
"",
"SAN FRANCISCO",
"CA",
"94107",
"US"
},
{
"zip",
37.371991,
-1.22026e+2,
"",
"SUNNYVALE",
"CA",
"94085",
"US"
}
};
volatile double zero = 0.0;
/* Here we construct some JSON standards, from the JSON site. */
/* Our "Video" datatype: */
root = cJSON_CreateObject();
cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
cJSON_AddStringToObject(fmt, "type", "rect");
cJSON_AddNumberToObject(fmt, "width", 1920);
cJSON_AddNumberToObject(fmt, "height", 1080);
cJSON_AddFalseToObject (fmt, "interlace");
cJSON_AddNumberToObject(fmt, "frame rate", 24);
/* Print to text */
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
/* Our "days of the week" array: */
root = cJSON_CreateStringArray(strings, 7);
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
/* Our matrix: */
root = cJSON_CreateArray();
for (i = 0; i < 3; i++)
{
cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3));
}
/* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
/* Our "gallery" item: */
root = cJSON_CreateObject();
cJSON_AddItemToObject(root, "Image", img = cJSON_CreateObject());
cJSON_AddNumberToObject(img, "Width", 800);
cJSON_AddNumberToObject(img, "Height", 600);
cJSON_AddStringToObject(img, "Title", "View from 15th Floor");
cJSON_AddItemToObject(img, "Thumbnail", thm = cJSON_CreateObject());
cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943");
cJSON_AddNumberToObject(thm, "Height", 125);
cJSON_AddStringToObject(thm, "Width", "100");
cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4));
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
/* Our array of "records": */
root = cJSON_CreateArray();
for (i = 0; i < 2; i++)
{
cJSON_AddItemToArray(root, fld = cJSON_CreateObject());
cJSON_AddStringToObject(fld, "precision", fields[i].precision);
cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat);
cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon);
cJSON_AddStringToObject(fld, "Address", fields[i].address);
cJSON_AddStringToObject(fld, "City", fields[i].city);
cJSON_AddStringToObject(fld, "State", fields[i].state);
cJSON_AddStringToObject(fld, "Zip", fields[i].zip);
cJSON_AddStringToObject(fld, "Country", fields[i].country);
}
/* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "number", 1.0 / zero);
if (print_preallocated(root) != 0) {
cJSON_Delete(root);
exit(EXIT_FAILURE);
}
cJSON_Delete(root);
}
int CJSON_CDECL main(void)
{
/* print the version */
printf("Version: %s\n", cJSON_Version());
/* Now some samplecode for building objects concisely: */
create_objects();
return 0;
}

View File

@@ -0,0 +1,119 @@
if(ENABLE_CJSON_TEST)
add_library(unity STATIC unity/src/unity.c)
# Disable -Werror for Unity
if (FLAG_SUPPORTED_Werror)
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error")
else()
target_compile_options(unity PRIVATE "-Wno-error")
endif()
endif()
# Disable -fvisibility=hidden for Unity
if (FLAG_SUPPORTED_fvisibilityhidden)
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=default")
else()
target_compile_options(unity PRIVATE "-fvisibility=default")
endif()
endif()
# Disable -fsanitize=float-divide-by-zero for Unity (GCC bug on x86 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80097)
if (FLAG_SUPPORTED_fsanitizefloatdividebyzero AND (CMAKE_C_COMPILER_ID STREQUAL "GNU"))
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-sanitize=float-divide-by-zero")
else()
target_compile_options(unity PRIVATE "-fno-sanitize=float-divide-by-zero")
endif()
endif()
# Disable -Wswitch-enum for Unity
if (FLAG_SUPPORTED_Wswitchenum)
if ("${CMAKE_VERSION}" VERSION_LESS "2.8.12")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-switch-enum")
else()
target_compile_options(unity PRIVATE "-Wno-switch-enum")
endif()
endif()
#copy test files
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/inputs")
file(GLOB test_files "inputs/*")
file(COPY ${test_files} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/inputs/")
set(unity_tests
parse_examples
parse_number
parse_hex4
parse_string
parse_array
parse_object
parse_value
print_string
print_number
print_array
print_object
print_value
misc_tests
parse_with_opts
compare_tests
cjson_add
readme_examples
minify_tests
)
option(ENABLE_VALGRIND OFF "Enable the valgrind memory checker for the tests.")
if (ENABLE_VALGRIND)
find_program(MEMORYCHECK_COMMAND valgrind)
if ("${MEMORYCHECK_COMMAND}" MATCHES "MEMORYCHECK_COMMAND-NOTFOUND")
message(WARNING "Valgrind couldn't be found.")
unset(MEMORYCHECK_COMMAND)
else()
set(MEMORYCHECK_COMMAND_OPTIONS --trace-children=yes --leak-check=full --error-exitcode=1 --suppressions=${CMAKE_CURRENT_SOURCE_DIR}/../valgrind.supp)
endif()
endif()
foreach(unity_test ${unity_tests})
add_executable("${unity_test}" "${unity_test}.c")
if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
target_sources(${unity_test} PRIVATE unity_setup.c)
endif()
target_link_libraries("${unity_test}" "${CJSON_LIB}" unity)
if(MEMORYCHECK_COMMAND)
add_test(NAME "${unity_test}"
COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${unity_test}")
else()
add_test(NAME "${unity_test}"
COMMAND "./${unity_test}")
endif()
endforeach()
add_dependencies(check ${unity_tests})
if (ENABLE_CJSON_UTILS)
#copy test files
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/json-patch-tests")
file(GLOB test_files "json-patch-tests/*")
file(COPY ${test_files} DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/json-patch-tests/")
set (cjson_utils_tests
json_patch_tests
old_utils_tests
misc_utils_tests)
foreach (cjson_utils_test ${cjson_utils_tests})
add_executable("${cjson_utils_test}" "${cjson_utils_test}.c")
target_link_libraries("${cjson_utils_test}" "${CJSON_LIB}" "${CJSON_UTILS_LIB}" unity)
if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC")
target_sources(${cjson_utils_test} PRIVATE unity_setup.c)
endif()
if(MEMORYCHECK_COMMAND)
add_test(NAME "${cjson_utils_test}"
COMMAND "${MEMORYCHECK_COMMAND}" ${MEMORYCHECK_COMMAND_OPTIONS} "${CMAKE_CURRENT_BINARY_DIR}/${cjson_utils_test}")
else()
add_test(NAME "${cjson_utils_test}"
COMMAND "./${cjson_utils_test}")
endif()
endforeach()
add_dependencies(check ${cjson_utils_tests})
endif()
endif()

View File

@@ -0,0 +1,471 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "unity/examples/unity_config.h"
#include "unity/src/unity.h"
#include "common.h"
static void * CJSON_CDECL failing_malloc(size_t size)
{
(void)size;
return NULL;
}
/* work around MSVC error C2322: '...' address of dillimport '...' is not static */
static void CJSON_CDECL normal_free(void *pointer)
{
free(pointer);
}
static cJSON_Hooks failing_hooks = {
failing_malloc,
normal_free
};
static void cjson_add_null_should_add_null(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *null = NULL;
cJSON_AddNullToObject(root, "null");
TEST_ASSERT_NOT_NULL(null = cJSON_GetObjectItemCaseSensitive(root, "null"));
TEST_ASSERT_EQUAL_INT(null->type, cJSON_NULL);
cJSON_Delete(root);
}
static void cjson_add_null_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddNullToObject(NULL, "null"));
TEST_ASSERT_NULL(cJSON_AddNullToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_null_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddNullToObject(root, "null"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_true_should_add_true(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *true_item = NULL;
cJSON_AddTrueToObject(root, "true");
TEST_ASSERT_NOT_NULL(true_item = cJSON_GetObjectItemCaseSensitive(root, "true"));
TEST_ASSERT_EQUAL_INT(true_item->type, cJSON_True);
cJSON_Delete(root);
}
static void cjson_add_true_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddTrueToObject(NULL, "true"));
TEST_ASSERT_NULL(cJSON_AddTrueToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_true_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddTrueToObject(root, "true"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_create_int_array_should_fail_on_allocation_failure(void)
{
int numbers[] = {1, 2, 3};
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_CreateIntArray(numbers, 3));
cJSON_InitHooks(NULL);
}
static void cjson_create_float_array_should_fail_on_allocation_failure(void)
{
float numbers[] = {1.0f, 2.0f, 3.0f};
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_CreateFloatArray(numbers, 3));
cJSON_InitHooks(NULL);
}
static void cjson_create_double_array_should_fail_on_allocation_failure(void)
{
double numbers[] = {1.0, 2.0, 3.0};
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_CreateDoubleArray(numbers, 3));
cJSON_InitHooks(NULL);
}
static void cjson_create_string_array_should_fail_on_allocation_failure(void)
{
const char* strings[] = {"1", "2", "3"};
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_CreateStringArray(strings, 3));
cJSON_InitHooks(NULL);
}
static void cjson_add_false_should_add_false(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *false_item = NULL;
cJSON_AddFalseToObject(root, "false");
TEST_ASSERT_NOT_NULL(false_item = cJSON_GetObjectItemCaseSensitive(root, "false"));
TEST_ASSERT_EQUAL_INT(false_item->type, cJSON_False);
cJSON_Delete(root);
}
static void cjson_add_false_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddFalseToObject(NULL, "false"));
TEST_ASSERT_NULL(cJSON_AddFalseToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_false_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddFalseToObject(root, "false"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_bool_should_add_bool(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *true_item = NULL;
cJSON *false_item = NULL;
/* true */
cJSON_AddBoolToObject(root, "true", true);
TEST_ASSERT_NOT_NULL(true_item = cJSON_GetObjectItemCaseSensitive(root, "true"));
TEST_ASSERT_EQUAL_INT(true_item->type, cJSON_True);
/* false */
cJSON_AddBoolToObject(root, "false", false);
TEST_ASSERT_NOT_NULL(false_item = cJSON_GetObjectItemCaseSensitive(root, "false"));
TEST_ASSERT_EQUAL_INT(false_item->type, cJSON_False);
cJSON_Delete(root);
}
static void cjson_add_bool_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddBoolToObject(NULL, "false", false));
TEST_ASSERT_NULL(cJSON_AddBoolToObject(root, NULL, false));
cJSON_Delete(root);
}
static void cjson_add_bool_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddBoolToObject(root, "false", false));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_number_should_add_number(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *number = NULL;
cJSON_AddNumberToObject(root, "number", 42);
TEST_ASSERT_NOT_NULL(number = cJSON_GetObjectItemCaseSensitive(root, "number"));
TEST_ASSERT_EQUAL_INT(number->type, cJSON_Number);
TEST_ASSERT_EQUAL_DOUBLE(number->valuedouble, 42);
TEST_ASSERT_EQUAL_INT(number->valueint, 42);
cJSON_Delete(root);
}
static void cjson_add_number_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddNumberToObject(NULL, "number", 42));
TEST_ASSERT_NULL(cJSON_AddNumberToObject(root, NULL, 42));
cJSON_Delete(root);
}
static void cjson_add_number_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddNumberToObject(root, "number", 42));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_string_should_add_string(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *string = NULL;
cJSON_AddStringToObject(root, "string", "Hello World!");
TEST_ASSERT_NOT_NULL(string = cJSON_GetObjectItemCaseSensitive(root, "string"));
TEST_ASSERT_EQUAL_INT(string->type, cJSON_String);
TEST_ASSERT_EQUAL_STRING(string->valuestring, "Hello World!");
cJSON_Delete(root);
}
static void cjson_add_string_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddStringToObject(NULL, "string", "string"));
TEST_ASSERT_NULL(cJSON_AddStringToObject(root, NULL, "string"));
cJSON_Delete(root);
}
static void cjson_add_string_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddStringToObject(root, "string", "string"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cjson_add_raw_should_add_raw(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *raw = NULL;
cJSON_AddRawToObject(root, "raw", "{}");
TEST_ASSERT_NOT_NULL(raw = cJSON_GetObjectItemCaseSensitive(root, "raw"));
TEST_ASSERT_EQUAL_INT(raw->type, cJSON_Raw);
TEST_ASSERT_EQUAL_STRING(raw->valuestring, "{}");
cJSON_Delete(root);
}
static void cjson_add_raw_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddRawToObject(NULL, "raw", "{}"));
TEST_ASSERT_NULL(cJSON_AddRawToObject(root, NULL, "{}"));
cJSON_Delete(root);
}
static void cjson_add_raw_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddRawToObject(root, "raw", "{}"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cJSON_add_object_should_add_object(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *object = NULL;
cJSON_AddObjectToObject(root, "object");
TEST_ASSERT_NOT_NULL(object = cJSON_GetObjectItemCaseSensitive(root, "object"));
TEST_ASSERT_EQUAL_INT(object->type, cJSON_Object);
cJSON_Delete(root);
}
static void cjson_add_object_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddObjectToObject(NULL, "object"));
TEST_ASSERT_NULL(cJSON_AddObjectToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_object_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddObjectToObject(root, "object"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
static void cJSON_add_array_should_add_array(void)
{
cJSON *root = cJSON_CreateObject();
cJSON *array = NULL;
cJSON_AddArrayToObject(root, "array");
TEST_ASSERT_NOT_NULL(array = cJSON_GetObjectItemCaseSensitive(root, "array"));
TEST_ASSERT_EQUAL_INT(array->type, cJSON_Array);
cJSON_Delete(root);
}
static void cjson_add_array_should_fail_with_null_pointers(void)
{
cJSON *root = cJSON_CreateObject();
TEST_ASSERT_NULL(cJSON_AddArrayToObject(NULL, "array"));
TEST_ASSERT_NULL(cJSON_AddArrayToObject(root, NULL));
cJSON_Delete(root);
}
static void cjson_add_array_should_fail_on_allocation_failure(void)
{
cJSON *root = cJSON_CreateObject();
cJSON_InitHooks(&failing_hooks);
TEST_ASSERT_NULL(cJSON_AddArrayToObject(root, "array"));
cJSON_InitHooks(NULL);
cJSON_Delete(root);
}
int CJSON_CDECL main(void)
{
UNITY_BEGIN();
RUN_TEST(cjson_add_null_should_add_null);
RUN_TEST(cjson_add_null_should_fail_with_null_pointers);
RUN_TEST(cjson_add_null_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_true_should_add_true);
RUN_TEST(cjson_add_true_should_fail_with_null_pointers);
RUN_TEST(cjson_add_true_should_fail_on_allocation_failure);
RUN_TEST(cjson_create_int_array_should_fail_on_allocation_failure);
RUN_TEST(cjson_create_float_array_should_fail_on_allocation_failure);
RUN_TEST(cjson_create_double_array_should_fail_on_allocation_failure);
RUN_TEST(cjson_create_string_array_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_false_should_add_false);
RUN_TEST(cjson_add_false_should_fail_with_null_pointers);
RUN_TEST(cjson_add_false_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_bool_should_add_bool);
RUN_TEST(cjson_add_bool_should_fail_with_null_pointers);
RUN_TEST(cjson_add_bool_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_number_should_add_number);
RUN_TEST(cjson_add_number_should_fail_with_null_pointers);
RUN_TEST(cjson_add_number_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_string_should_add_string);
RUN_TEST(cjson_add_string_should_fail_with_null_pointers);
RUN_TEST(cjson_add_string_should_fail_on_allocation_failure);
RUN_TEST(cjson_add_raw_should_add_raw);
RUN_TEST(cjson_add_raw_should_fail_with_null_pointers);
RUN_TEST(cjson_add_raw_should_fail_on_allocation_failure);
RUN_TEST(cJSON_add_object_should_add_object);
RUN_TEST(cjson_add_object_should_fail_with_null_pointers);
RUN_TEST(cjson_add_object_should_fail_on_allocation_failure);
RUN_TEST(cJSON_add_array_should_add_array);
RUN_TEST(cjson_add_array_should_fail_with_null_pointers);
RUN_TEST(cjson_add_array_should_fail_on_allocation_failure);
return UNITY_END();
}

View File

@@ -0,0 +1,122 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef CJSON_TESTS_COMMON_H
#define CJSON_TESTS_COMMON_H
#include "../cJSON.c"
void reset(cJSON *item);
void reset(cJSON *item) {
if ((item != NULL) && (item->child != NULL))
{
cJSON_Delete(item->child);
}
if ((item->valuestring != NULL) && !(item->type & cJSON_IsReference))
{
global_hooks.deallocate(item->valuestring);
}
if ((item->string != NULL) && !(item->type & cJSON_StringIsConst))
{
global_hooks.deallocate(item->string);
}
memset(item, 0, sizeof(cJSON));
}
char* read_file(const char *filename);
char* read_file(const char *filename) {
FILE *file = NULL;
long length = 0;
char *content = NULL;
size_t read_chars = 0;
/* open in read binary mode */
file = fopen(filename, "rb");
if (file == NULL)
{
goto cleanup;
}
/* get the length */
if (fseek(file, 0, SEEK_END) != 0)
{
goto cleanup;
}
length = ftell(file);
if (length < 0)
{
goto cleanup;
}
if (fseek(file, 0, SEEK_SET) != 0)
{
goto cleanup;
}
/* allocate content buffer */
content = (char*)malloc((size_t)length + sizeof(""));
if (content == NULL)
{
goto cleanup;
}
/* read the file into memory */
read_chars = fread(content, sizeof(char), (size_t)length, file);
if ((long)read_chars != length)
{
free(content);
content = NULL;
goto cleanup;
}
content[read_chars] = '\0';
cleanup:
if (file != NULL)
{
fclose(file);
}
return content;
}
/* assertion helper macros */
#define assert_has_type(item, item_type) TEST_ASSERT_BITS_MESSAGE(0xFF, item_type, item->type, "Item doesn't have expected type.")
#define assert_has_no_reference(item) TEST_ASSERT_BITS_MESSAGE(cJSON_IsReference, 0, item->type, "Item should not have a string as reference.")
#define assert_has_no_const_string(item) TEST_ASSERT_BITS_MESSAGE(cJSON_StringIsConst, 0, item->type, "Item should not have a const string.")
#define assert_has_valuestring(item) TEST_ASSERT_NOT_NULL_MESSAGE(item->valuestring, "Valuestring is NULL.")
#define assert_has_no_valuestring(item) TEST_ASSERT_NULL_MESSAGE(item->valuestring, "Valuestring is not NULL.")
#define assert_has_string(item) TEST_ASSERT_NOT_NULL_MESSAGE(item->string, "String is NULL")
#define assert_has_no_string(item) TEST_ASSERT_NULL_MESSAGE(item->string, "String is not NULL.")
#define assert_not_in_list(item) \
TEST_ASSERT_NULL_MESSAGE(item->next, "Linked list next pointer is not NULL.");\
TEST_ASSERT_NULL_MESSAGE(item->prev, "Linked list previous pointer is not NULL.")
#define assert_has_child(item) TEST_ASSERT_NOT_NULL_MESSAGE(item->child, "Item doesn't have a child.")
#define assert_has_no_child(item) TEST_ASSERT_NULL_MESSAGE(item->child, "Item has a child.")
#define assert_is_invalid(item) \
assert_has_type(item, cJSON_Invalid);\
assert_not_in_list(item);\
assert_has_no_child(item);\
assert_has_no_string(item);\
assert_has_no_valuestring(item)
#endif

View File

@@ -0,0 +1,208 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "unity/examples/unity_config.h"
#include "unity/src/unity.h"
#include "common.h"
static cJSON_bool compare_from_string(const char * const a, const char * const b, const cJSON_bool case_sensitive)
{
cJSON *a_json = NULL;
cJSON *b_json = NULL;
cJSON_bool result = false;
a_json = cJSON_Parse(a);
TEST_ASSERT_NOT_NULL_MESSAGE(a_json, "Failed to parse a.");
b_json = cJSON_Parse(b);
TEST_ASSERT_NOT_NULL_MESSAGE(b_json, "Failed to parse b.");
result = cJSON_Compare(a_json, b_json, case_sensitive);
cJSON_Delete(a_json);
cJSON_Delete(b_json);
return result;
}
static void cjson_compare_should_compare_null_pointer_as_not_equal(void)
{
TEST_ASSERT_FALSE(cJSON_Compare(NULL, NULL, true));
TEST_ASSERT_FALSE(cJSON_Compare(NULL, NULL, false));
}
static void cjson_compare_should_compare_invalid_as_not_equal(void)
{
cJSON invalid[1];
memset(invalid, '\0', sizeof(invalid));
TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, false));
TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, true));
}
static void cjson_compare_should_compare_numbers(void)
{
TEST_ASSERT_TRUE(compare_from_string("1", "1", true));
TEST_ASSERT_TRUE(compare_from_string("1", "1", false));
TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", true));
TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", false));
TEST_ASSERT_TRUE(compare_from_string("1E100", "10E99", false));
TEST_ASSERT_FALSE(compare_from_string("0.5E-100", "0.5E-101", false));
TEST_ASSERT_FALSE(compare_from_string("1", "2", true));
TEST_ASSERT_FALSE(compare_from_string("1", "2", false));
}
static void cjson_compare_should_compare_booleans(void)
{
/* true */
TEST_ASSERT_TRUE(compare_from_string("true", "true", true));
TEST_ASSERT_TRUE(compare_from_string("true", "true", false));
/* false */
TEST_ASSERT_TRUE(compare_from_string("false", "false", true));
TEST_ASSERT_TRUE(compare_from_string("false", "false", false));
/* mixed */
TEST_ASSERT_FALSE(compare_from_string("true", "false", true));
TEST_ASSERT_FALSE(compare_from_string("true", "false", false));
TEST_ASSERT_FALSE(compare_from_string("false", "true", true));
TEST_ASSERT_FALSE(compare_from_string("false", "true", false));
}
static void cjson_compare_should_compare_null(void)
{
TEST_ASSERT_TRUE(compare_from_string("null", "null", true));
TEST_ASSERT_TRUE(compare_from_string("null", "null", false));
TEST_ASSERT_FALSE(compare_from_string("null", "true", true));
TEST_ASSERT_FALSE(compare_from_string("null", "true", false));
}
static void cjson_compare_should_not_accept_invalid_types(void)
{
cJSON invalid[1];
memset(invalid, '\0', sizeof(invalid));
invalid->type = cJSON_Number | cJSON_String;
TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, true));
TEST_ASSERT_FALSE(cJSON_Compare(invalid, invalid, false));
}
static void cjson_compare_should_compare_strings(void)
{
TEST_ASSERT_TRUE(compare_from_string("\"abcdefg\"", "\"abcdefg\"", true));
TEST_ASSERT_TRUE(compare_from_string("\"abcdefg\"", "\"abcdefg\"", false));
TEST_ASSERT_FALSE(compare_from_string("\"ABCDEFG\"", "\"abcdefg\"", true));
TEST_ASSERT_FALSE(compare_from_string("\"ABCDEFG\"", "\"abcdefg\"", false));
}
static void cjson_compare_should_compare_raw(void)
{
cJSON *raw1 = NULL;
cJSON *raw2 = NULL;
raw1 = cJSON_Parse("\"[true, false]\"");
TEST_ASSERT_NOT_NULL(raw1);
raw2 = cJSON_Parse("\"[true, false]\"");
TEST_ASSERT_NOT_NULL(raw2);
raw1->type = cJSON_Raw;
raw2->type = cJSON_Raw;
TEST_ASSERT_TRUE(cJSON_Compare(raw1, raw2, true));
TEST_ASSERT_TRUE(cJSON_Compare(raw1, raw2, false));
cJSON_Delete(raw1);
cJSON_Delete(raw2);
}
static void cjson_compare_should_compare_arrays(void)
{
TEST_ASSERT_TRUE(compare_from_string("[]", "[]", true));
TEST_ASSERT_TRUE(compare_from_string("[]", "[]", false));
TEST_ASSERT_TRUE(compare_from_string("[false,true,null,42,\"string\",[],{}]", "[false, true, null, 42, \"string\", [], {}]", true));
TEST_ASSERT_TRUE(compare_from_string("[false,true,null,42,\"string\",[],{}]", "[false, true, null, 42, \"string\", [], {}]", false));
TEST_ASSERT_TRUE(compare_from_string("[[[1], 2]]", "[[[1], 2]]", true));
TEST_ASSERT_TRUE(compare_from_string("[[[1], 2]]", "[[[1], 2]]", false));
TEST_ASSERT_FALSE(compare_from_string("[true,null,42,\"string\",[],{}]", "[false, true, null, 42, \"string\", [], {}]", true));
TEST_ASSERT_FALSE(compare_from_string("[true,null,42,\"string\",[],{}]", "[false, true, null, 42, \"string\", [], {}]", false));
/* Arrays that are a prefix of another array */
TEST_ASSERT_FALSE(compare_from_string("[1,2,3]", "[1,2]", true));
TEST_ASSERT_FALSE(compare_from_string("[1,2,3]", "[1,2]", false));
}
static void cjson_compare_should_compare_objects(void)
{
TEST_ASSERT_TRUE(compare_from_string("{}", "{}", true));
TEST_ASSERT_TRUE(compare_from_string("{}", "{}", false));
TEST_ASSERT_TRUE(compare_from_string(
"{\"false\": false, \"true\": true, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
"{\"true\": true, \"false\": false, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
true));
TEST_ASSERT_FALSE(compare_from_string(
"{\"False\": false, \"true\": true, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
"{\"true\": true, \"false\": false, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
true));
TEST_ASSERT_TRUE(compare_from_string(
"{\"False\": false, \"true\": true, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
"{\"true\": true, \"false\": false, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
false));
TEST_ASSERT_FALSE(compare_from_string(
"{\"Flse\": false, \"true\": true, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
"{\"true\": true, \"false\": false, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
false));
/* test objects that are a subset of each other */
TEST_ASSERT_FALSE(compare_from_string(
"{\"one\": 1, \"two\": 2}",
"{\"one\": 1, \"two\": 2, \"three\": 3}",
true))
TEST_ASSERT_FALSE(compare_from_string(
"{\"one\": 1, \"two\": 2}",
"{\"one\": 1, \"two\": 2, \"three\": 3}",
false))
}
int CJSON_CDECL main(void)
{
UNITY_BEGIN();
RUN_TEST(cjson_compare_should_compare_null_pointer_as_not_equal);
RUN_TEST(cjson_compare_should_compare_invalid_as_not_equal);
RUN_TEST(cjson_compare_should_compare_numbers);
RUN_TEST(cjson_compare_should_compare_booleans);
RUN_TEST(cjson_compare_should_compare_null);
RUN_TEST(cjson_compare_should_not_accept_invalid_types);
RUN_TEST(cjson_compare_should_compare_strings);
RUN_TEST(cjson_compare_should_compare_raw);
RUN_TEST(cjson_compare_should_compare_arrays);
RUN_TEST(cjson_compare_should_compare_objects);
return UNITY_END();
}

View File

@@ -0,0 +1,22 @@
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}

View File

@@ -0,0 +1,22 @@
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}

View File

@@ -0,0 +1 @@
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

View File

@@ -0,0 +1 @@
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]

View File

@@ -0,0 +1,8 @@
{
"name": "Jack (\"Bee\") Nimble",
"format": {"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,"frame rate": 24
}
}

View File

@@ -0,0 +1,10 @@
{
"name": "Jack (\"Bee\") Nimble",
"format": {
"type": "rect",
"width": 1920,
"height": 1080,
"interlace": false,
"frame rate": 24
}
}

View File

@@ -0,0 +1,11 @@
{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}

View File

@@ -0,0 +1,18 @@
{
"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [{
"value": "New",
"onclick": "CreateNewDoc()"
}, {
"value": "Open",
"onclick": "OpenDoc()"
}, {
"value": "Close",
"onclick": "CloseDoc()"
}]
}
}
}

View File

@@ -0,0 +1,26 @@
{"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}

View File

@@ -0,0 +1,28 @@
{
"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}
}

View File

@@ -0,0 +1,88 @@
{"web-app": {
"servlet": [
{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
"init-param": {
"configGlossary:installationAt": "Philadelphia, PA",
"configGlossary:adminEmail": "ksm@pobox.com",
"configGlossary:poweredBy": "Cofax",
"configGlossary:poweredByIcon": "/images/cofax.gif",
"configGlossary:staticPath": "/content/static",
"templateProcessorClass": "org.cofax.WysiwygTemplate",
"templateLoaderClass": "org.cofax.FilesTemplateLoader",
"templatePath": "templates",
"templateOverridePath": "",
"defaultListTemplate": "listTemplate.htm",
"defaultFileTemplate": "articleTemplate.htm",
"useJSP": false,
"jspListTemplate": "listTemplate.jsp",
"jspFileTemplate": "articleTemplate.jsp",
"cachePackageTagsTrack": 200,
"cachePackageTagsStore": 200,
"cachePackageTagsRefresh": 60,
"cacheTemplatesTrack": 100,
"cacheTemplatesStore": 50,
"cacheTemplatesRefresh": 15,
"cachePagesTrack": 200,
"cachePagesStore": 100,
"cachePagesRefresh": 10,
"cachePagesDirtyRead": 10,
"searchEngineListTemplate": "forSearchEnginesList.htm",
"searchEngineFileTemplate": "forSearchEngines.htm",
"searchEngineRobotsDb": "WEB-INF/robots.db",
"useDataStore": true,
"dataStoreClass": "org.cofax.SqlDataStore",
"redirectionClass": "org.cofax.SqlRedirection",
"dataStoreName": "cofax",
"dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
"dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
"dataStoreUser": "sa",
"dataStorePassword": "dataStoreTestQuery",
"dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
"dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
"dataStoreInitConns": 10,
"dataStoreMaxConns": 100,
"dataStoreConnUsageLimit": 100,
"dataStoreLogLevel": "debug",
"maxUrlLength": 500}},
{
"servlet-name": "cofaxEmail",
"servlet-class": "org.cofax.cds.EmailServlet",
"init-param": {
"mailHost": "mail1",
"mailHostOverride": "mail2"}},
{
"servlet-name": "cofaxAdmin",
"servlet-class": "org.cofax.cds.AdminServlet"},
{
"servlet-name": "fileServlet",
"servlet-class": "org.cofax.cds.FileServlet"},
{
"servlet-name": "cofaxTools",
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
"init-param": {
"templatePath": "toolstemplates/",
"log": 1,
"logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
"logMaxSize": "",
"dataLog": 1,
"dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
"dataLogMaxSize": "",
"removePageCache": "/content/admin/remove?cache=pages&id=",
"removeTemplateCache": "/content/admin/remove?cache=templates&id=",
"fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
"lookInContext": 1,
"adminGroupID": 4,
"betaServer": true}}],
"servlet-mapping": {
"cofaxCDS": "/",
"cofaxEmail": "/cofaxutil/aemail/*",
"cofaxAdmin": "/admin/*",
"fileServlet": "/static/*",
"cofaxTools": "/tools/*"},
"taglib": {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"}}}

View File

@@ -0,0 +1,94 @@
{
"web-app": {
"servlet": [{
"servlet-name": "cofaxCDS",
"servlet-class": "org.cofax.cds.CDSServlet",
"init-param": {
"configGlossary:installationAt": "Philadelphia, PA",
"configGlossary:adminEmail": "ksm@pobox.com",
"configGlossary:poweredBy": "Cofax",
"configGlossary:poweredByIcon": "/images/cofax.gif",
"configGlossary:staticPath": "/content/static",
"templateProcessorClass": "org.cofax.WysiwygTemplate",
"templateLoaderClass": "org.cofax.FilesTemplateLoader",
"templatePath": "templates",
"templateOverridePath": "",
"defaultListTemplate": "listTemplate.htm",
"defaultFileTemplate": "articleTemplate.htm",
"useJSP": false,
"jspListTemplate": "listTemplate.jsp",
"jspFileTemplate": "articleTemplate.jsp",
"cachePackageTagsTrack": 200,
"cachePackageTagsStore": 200,
"cachePackageTagsRefresh": 60,
"cacheTemplatesTrack": 100,
"cacheTemplatesStore": 50,
"cacheTemplatesRefresh": 15,
"cachePagesTrack": 200,
"cachePagesStore": 100,
"cachePagesRefresh": 10,
"cachePagesDirtyRead": 10,
"searchEngineListTemplate": "forSearchEnginesList.htm",
"searchEngineFileTemplate": "forSearchEngines.htm",
"searchEngineRobotsDb": "WEB-INF/robots.db",
"useDataStore": true,
"dataStoreClass": "org.cofax.SqlDataStore",
"redirectionClass": "org.cofax.SqlRedirection",
"dataStoreName": "cofax",
"dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
"dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
"dataStoreUser": "sa",
"dataStorePassword": "dataStoreTestQuery",
"dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
"dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
"dataStoreInitConns": 10,
"dataStoreMaxConns": 100,
"dataStoreConnUsageLimit": 100,
"dataStoreLogLevel": "debug",
"maxUrlLength": 500
}
}, {
"servlet-name": "cofaxEmail",
"servlet-class": "org.cofax.cds.EmailServlet",
"init-param": {
"mailHost": "mail1",
"mailHostOverride": "mail2"
}
}, {
"servlet-name": "cofaxAdmin",
"servlet-class": "org.cofax.cds.AdminServlet"
}, {
"servlet-name": "fileServlet",
"servlet-class": "org.cofax.cds.FileServlet"
}, {
"servlet-name": "cofaxTools",
"servlet-class": "org.cofax.cms.CofaxToolsServlet",
"init-param": {
"templatePath": "toolstemplates/",
"log": 1,
"logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
"logMaxSize": "",
"dataLog": 1,
"dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
"dataLogMaxSize": "",
"removePageCache": "/content/admin/remove?cache=pages&id=",
"removeTemplateCache": "/content/admin/remove?cache=templates&id=",
"fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
"lookInContext": 1,
"adminGroupID": 4,
"betaServer": true
}
}],
"servlet-mapping": {
"cofaxCDS": "/",
"cofaxEmail": "/cofaxutil/aemail/*",
"cofaxAdmin": "/admin/*",
"fileServlet": "/static/*",
"cofaxTools": "/tools/*"
},
"taglib": {
"taglib-uri": "cofax.tld",
"taglib-location": "/WEB-INF/tlds/cofax.tld"
}
}
}

View File

@@ -0,0 +1,27 @@
{"menu": {
"header": "SVG Viewer",
"items": [
{"id": "Open"},
{"id": "OpenNew", "label": "Open New"},
null,
{"id": "ZoomIn", "label": "Zoom In"},
{"id": "ZoomOut", "label": "Zoom Out"},
{"id": "OriginalView", "label": "Original View"},
null,
{"id": "Quality"},
{"id": "Pause"},
{"id": "Mute"},
null,
{"id": "Find", "label": "Find..."},
{"id": "FindAgain", "label": "Find Again"},
{"id": "Copy"},
{"id": "CopyAgain", "label": "Copy Again"},
{"id": "CopySVG", "label": "Copy SVG"},
{"id": "ViewSVG", "label": "View SVG"},
{"id": "ViewSource", "label": "View Source"},
{"id": "SaveAs", "label": "Save As"},
null,
{"id": "Help"},
{"id": "About", "label": "About Adobe CVG Viewer..."}
]
}}

Some files were not shown because too many files have changed in this diff Show More