xref: /haiku/docs/user/support/Flattenable.dox (revision b617a7b410c05275effb95f4b2f5608359d9b7b9)
1/*
2 * Copyright 2007 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Niels Sascha Reedijk <niels.reedijk@gmail.com>
7 *
8 * Corresponds to:
9 *		headers/os/support/Flattenable.h	rev 39675
10 *		src/kits/support/Flattenable.cpp	rev 12963
11 */
12
13
14/*!
15	\file Flattenable.h
16	\ingroup support
17	\ingroup libbe
18	\brief Provides the BFlattenable interface
19*/
20
21
22/*!
23	\class BFlattenable
24	\ingroup support
25	\ingroup libbe
26	\brief Interface for classes that can flatten and unflatten themselves to
27		   a stream of bytes.
28
29	It is convenient that objects can be stored as a flat stream of bytes. In
30	this way, they can be written to disk, exchanged between applications or send
31	over networks. This ability, which is known in many other programming
32	languages as marshalling, is not native in C++. The Haiku API has created a
33	universal interface that classes have if they are able to be flattened. This
34	class defines the interface. This class does nothing on its own, and
35	therefore contains pure virtuals. By inheriting this class and inmplementing
36	the methods in your own class, you will be able to use your objects as
37	flattenable objects throughout the Haiku API.
38
39	Flattened objects can be used for example when sending messages within an
40	application or between applications. The BMessage class uses the interface
41	to store and transmit custom classes.
42
43	If you want to be able to flatten your objects, you will need to implement
44	various methods. Flatten() and Unflatten() are where the magic happen. These
45	methods handle the actual flattening and unflattening. To identify flattened
46	data in for example BMessage, the object has a type_code. Type codes are
47	four byte long integers. You can choose to flatten to one of the existing
48	types, if you are certain that you are compatible to those, but you'll
49	usually define your own type. Your best option is by using a multicharacter
50	constant, such as 'STRI'. Implement TypeCode() to return the type you
51	support. Implement FlattenedSize() to make sure that other objects can
52	provide the right buffers. Implement IsFixedSize() to return whether your
53	objects always store to a fixed size.
54
55	See the following example:
56\code
57type_code CUSTOM_STRING_TYPE = 'CUST';
58
59class CustomString : public BFlattenable
60{
61public:
62    char data[100];
63
64    // From BFlattenable
65    bool IsFixedSize() const { return false; };
66    type_code TypeCode() const { return CUSTOM_STRING_TYPE; };
67    ssize_t FlattenedSize() const { return strlen(data); };
68
69    status_t Flatten(void* buffer, ssize_t size) const
70    {
71        if ((strlen(data) + 1) < size)
72            return B_BAD_VALUE;
73        memcpy(buffer, data, size);
74        return B_OK;
75    };
76
77    status_t Unflatten(type_code code, const void* buffer, ssize_t size)
78    {
79        if (code != CUSTOM_STRING_TYPE)
80            return B_BAD_TYPE;
81        if (size > 100)
82            return B_NO_MEMORY;
83        memcpy(data, buffer, size);
84        return B_OK;
85    };
86};
87\endcode
88
89	Have a look at TypeConstants.h for a list of all the types that the Haiku
90	API defines.
91
92	The Haiku API has a second interface for storing objects, which is with
93	BArchivable. BArchivable is for more complex cases. Instead of one flat
94	datastream, it stores an object in a BMessage. In that way you can reflect
95	internals of a class better. It also provides an interface for instantiating
96	objects, that is, for objects to restore themselves from a BMessage. In
97	essence, BArchivable is more suitable for objects that are alive. In short
98	BFlattenable is for data objects, BArchivable is for 'live' objects.
99
100	Other classes in the API that support flattening and unflattening are for
101	example BMessage, which enables you to conveniently write flattened data
102	to disk. Another example is BPath. Because of that you can store paths and
103	send them over via messages. Throughout the Haiku API you will find classes
104	that provide the flattening interface.
105*/
106
107
108/*!
109	\fn virtual bool BFlattenable::IsFixedSize() const
110	\brief Pure virtual that should return whether or not flattened objects of
111		   this type always have a fixed size.
112*/
113
114
115/*!
116	\fn virtual type_code BFlattenable::TypeCode() const
117	\brief Pure virtual that returns the type_code this class flattens to.
118
119	\return Either one of the existing typecodes found in TypeConstants.h
120		if your class actually is compatible to those formats, or a
121		custom four-byte integer constant if not.
122*/
123
124
125/*!
126	\fn virtual ssize_t BFlattenable::FlattenedSize() const
127	\brief Pure virtual that should return the size of the flattened object in
128		   bytes.
129*/
130
131
132/*!
133	\fn virtual status_t BFlattenable::Flatten(void* buffer, ssize_t size) const
134	\brief Pure virtual that should flatten the object into the supplied
135		   \a buffer.
136
137	Please make sure that you check that the supplied buffer is not a \c NULL
138	pointer. Also make sure that the size of the flattened object does isn't
139	larger than the size of the buffer.
140
141	\param buffer The buffer to flatten in.
142	\param size The size of the buffer.
143
144	\retval B_OK The object was flattened.
145	\retval B_NO_MEMORY The buffer was smaller than required.
146	\retval B_BAD_VALUE The buffer was a \c NULL pointer.
147*/
148
149
150/*!
151	\fn bool BFlattenable::AllowsTypeCode(type_code code) const
152	\brief Get whether or not the supplied type_code is supported.
153
154	This default implementation checks the \a code argument against the type_code
155	returned by TypeCode().
156
157	\param code The type_code constant you want to check for.
158
159	\returns Whether or not the supplied type_code is supported.
160	\retval true The type_code is supported.
161	\retval false The type_code is not supported.
162*/
163
164
165/*!
166	\fn virtual status_t BFlattenable::Unflatten(type_code code,
167		const void* buffer, ssize_t size)
168	\brief Pure virtual that should unflatten the buffer and put the contents
169		   into the current object.
170
171	Make sure that the supplied buffer is not \c NULL and that you actually
172	support the typecode.
173
174	\param code The type_code this data is.
175	\param buffer The buffer to unflatten the data from.
176	\param size The size of the data.
177
178	\returns A status code.
179	\retval B_OK The object is unflattened.
180	\retval B_BAD_VALUE The \a buffer pointer is \c NULL or the data is invalid.
181	\retval B_BAD_TYPE You don't support data with this \a code.
182*/
183
184
185/*!
186	\fn virtual BFlattenable::~BFlattenable()
187	\brief Destructor. Does nothing.
188*/
189