1//----------------------------------------------------------------------
2//  This software is part of the Haiku distribution and is covered
3//  by the MIT License.
4//---------------------------------------------------------------------
5/*!
6	\file Supertype.cpp
7	Supertype class implementation
8*/
9
10#include <mime/Supertype.h>
11
12#include <Message.h>
13#include <mime/database_support.h>
14
15#include <new>
16#include <stdio.h>
17
18#define DBG(x) x
19//#define DBG(x)
20#define OUT printf
21
22namespace BPrivate {
23namespace Storage {
24namespace Mime {
25
26/*!
27	\class Supertype
28	\brief Installed types information for a single supertype
29*/
30
31// Constructor
32//! Constructs a new Supertype object
33Supertype::Supertype(const char *super)
34	: fCachedMessage(NULL)
35	, fName(super ? super : "")
36{
37}
38
39// Destructor
40//! Destroys the Supertype object
41Supertype::~Supertype()
42{
43	delete fCachedMessage;
44}
45
46// GetInstalledSubtypes
47/*! \brief Returns a list of the installeds subtypes for this supertype
48	in the pre-allocated \c BMessage pointed to by \c types.
49*/
50status_t
51Supertype::GetInstalledSubtypes(BMessage *types)
52{
53	status_t err = types ? B_OK : B_BAD_VALUE;
54	// See if we need to fill up a new message
55	if (!err && !fCachedMessage) {
56		err = CreateMessageWithTypes(&fCachedMessage);
57	}
58	// If we get this far, there's a cached message waiting
59	if (!err) {
60		*types = *fCachedMessage;
61	}
62	return err;
63}
64
65// AddSubtype
66/*! \brief Adds the given subtype to the subtype list and the cached message,
67	if one exists.
68	\param sub The subtype to add (do not include the supertype)
69	\return
70	- B_OK: success
71	- B_NAME_IN_USE: The subtype already exists in the subtype list
72	- "error code": failure
73*/
74status_t
75Supertype::AddSubtype(const char *sub)
76{
77	status_t err = sub ? B_OK : B_BAD_VALUE;
78	if (!err)
79		err = fSubtypes.insert(sub).second ? B_OK : B_NAME_IN_USE;
80	if (!err && fCachedMessage) {
81		char type[B_PATH_NAME_LENGTH];
82		sprintf(type, "%s/%s", fName.c_str(), sub);
83		err = fCachedMessage->AddString("types", type);
84	}
85	return err;
86}
87
88// RemoveSubtype
89/*! \brief Removes the given subtype from the subtype list and invalidates the
90	cached message,	if one exists.
91	\param sub The subtype to remove (do not include the supertype)
92*/
93status_t
94Supertype::RemoveSubtype(const char *sub)
95{
96	status_t err = sub ? B_OK : B_BAD_VALUE;
97	if (!err)
98		err = fSubtypes.erase(sub) == 1 ? B_OK : B_NAME_NOT_FOUND;
99	if (!err && fCachedMessage) {
100		delete fCachedMessage;
101		fCachedMessage = NULL;
102	}
103	return err;
104}
105
106// SetName
107//! Sets the supertype's name
108void
109Supertype::SetName(const char *super)
110{
111	if (super)
112		fName = super;
113}
114
115// GetName
116//! Returns the supertype's name
117const char*
118Supertype::GetName()
119{
120	return fName.c_str();
121}
122
123// FillMessageWithTypes
124//! Adds the supertype's subtypes to the given message
125/*! Each subtype is added as another item in the message's \c Mime::kTypesField
126	field. The complete type ("supertype/subtype") is added. The supertype itself
127	is not added to the message.
128*/
129status_t
130Supertype::FillMessageWithTypes(BMessage &msg) const
131{
132	status_t err = B_OK;
133	std::set<std::string>::const_iterator i;
134	for (i = fSubtypes.begin(); i != fSubtypes.end() && !err; i++) {
135		char type[B_PATH_NAME_LENGTH];
136		sprintf(type, "%s/%s", fName.c_str(), (*i).c_str());
137		err = msg.AddString(kTypesField, type);
138	}
139	return err;
140}
141
142// CreateMessageWithTypes
143/*! \brief Allocates a new BMessage into the BMessage pointer pointed to by \c result
144	and fills it with the supertype's subtypes.
145
146	See \c Supertype::FillMessageWithTypes() for more information.
147*/
148status_t
149Supertype::CreateMessageWithTypes(BMessage **result) const
150{
151	status_t err = result ? B_OK : B_BAD_VALUE;
152	// Alloc the message
153	if (!err) {
154		try {
155			*result = new BMessage();
156		} catch (std::bad_alloc&) {
157			err = B_NO_MEMORY;
158		}
159	}
160	// Fill with types
161	if (!err)
162		err = FillMessageWithTypes(**result);
163	return err;
164}
165
166} // namespace Mime
167} // namespace Storage
168} // namespace BPrivate
169
170